This is an R Markdown Notebook. When you execute code within the notebook, the results appear beneath the code.

Try executing this chunk by clicking the Run button within the chunk or by placing your cursor inside it and pressing Ctrl+Shift+Enter.

# general visualisation
library('ggplot2') # visualisation
Registered S3 method overwritten by 'dplyr':
  method           from
  print.rowwise_df     
Use suppressPackageStartupMessages() to eliminate package startup messages

Attaching package: 㤼㸱ggplot2㤼㸲

The following object is masked from 㤼㸱package:dlm㤼㸲:

    %+%
library('scales') # visualisation
library('patchwork') # visualisation

Attaching package: 㤼㸱patchwork㤼㸲

The following object is masked from 㤼㸱package:MASS㤼㸲:

    area
library('RColorBrewer') # visualisation
library('corrplot') # visualisation
corrplot 0.84 loaded
# general data manipulation
library('dplyr') # data manipulation

Attaching package: 㤼㸱dplyr㤼㸲

The following object is masked from 㤼㸱package:MASS㤼㸲:

    select

The following objects are masked from 㤼㸱package:stats㤼㸲:

    filter, lag

The following objects are masked from 㤼㸱package:base㤼㸲:

    intersect, setdiff, setequal, union
library('readr') # input/output

Attaching package: 㤼㸱readr㤼㸲

The following object is masked from 㤼㸱package:scales㤼㸲:

    col_factor

The following object is masked from 㤼㸱package:TSA㤼㸲:

    spec
library('vroom') # input/output
library('skimr') # overview
Registered S3 methods overwritten by 'htmltools':
  method               from         
  print.html           tools:rstudio
  print.shiny.tag      tools:rstudio
  print.shiny.tag.list tools:rstudio
library('tibble') # data wrangling
library('tidyr') # data wrangling
library('purrr') # data wrangling

Attaching package: 㤼㸱purrr㤼㸲

The following object is masked from 㤼㸱package:scales㤼㸲:

    discard
library('stringr') # string manipulation
library('forcats') # factor manipulation

# specific visualisation
library('alluvial') # visualisation
library('ggrepel') # visualisation
library('ggforce') # visualisation
library('ggridges') # visualisation
library('gganimate') # animations
No renderer backend detected. gganimate will default to writing frames to separate files
Consider installing:
- the `gifski` package for gif output
- the `av` package for video output
and restarting the R session
library('GGally') # visualisation
Registered S3 method overwritten by 'GGally':
  method from   
  +.gg   ggplot2

Attaching package: 㤼㸱GGally㤼㸲

The following object is masked from 㤼㸱package:dplyr㤼㸲:

    nasa
library('ggthemes') # visualisation
library('wesanderson') # visualisation
library('kableExtra') # display

Attaching package: 㤼㸱kableExtra㤼㸲

The following object is masked from 㤼㸱package:dplyr㤼㸲:

    group_rows
# Date + forecast
library('lubridate') # date and time

Attaching package: 㤼㸱lubridate㤼㸲

The following objects are masked from 㤼㸱package:dplyr㤼㸲:

    intersect, setdiff, union

The following objects are masked from 㤼㸱package:base㤼㸲:

    date, intersect, setdiff, union
library('forecast') # time series analysis
Registered S3 method overwritten by 'quantmod':
  method            from
  as.zoo.data.frame zoo 
Registered S3 methods overwritten by 'forecast':
  method       from
  fitted.Arima TSA 
  plot.Arima   TSA 
This is forecast 8.12 
  Need help getting started? Try the online textbook FPP:
  http://OTexts.org/fpp2/
#library('prophet') # time series analysis
library('timetk') # time series analysis

# Interactivity
library('crosstalk')
library('plotly')
Registered S3 method overwritten by 'data.table':
  method           from
  print.data.table     
Registered S3 method overwritten by 'htmlwidgets':
  method           from         
  print.htmlwidget tools:rstudio

Attaching package: 㤼㸱plotly㤼㸲

The following object is masked from 㤼㸱package:ggplot2㤼㸲:

    last_plot

The following object is masked from 㤼㸱package:MASS㤼㸲:

    select

The following object is masked from 㤼㸱package:stats㤼㸲:

    filter

The following object is masked from 㤼㸱package:graphics㤼㸲:

    layout
# parallel
library('foreach')

Attaching package: 㤼㸱foreach㤼㸲

The following objects are masked from 㤼㸱package:purrr㤼㸲:

    accumulate, when
library('doParallel')
Loading required package: iterators
Loading required package: parallel
library(vroom)
library(stringr)
library(tidyverse)
Registered S3 methods overwritten by 'dbplyr':
  method         from
  print.tbl_lazy     
  print.tbl_sql      
train <- vroom(str_c('/Coursework/Timeseries/Timeseries_project/CSV files/sales_train_validation.csv'), delim = ",", col_types = cols())
prices <- vroom(str_c('/Coursework/Timeseries/Timeseries_project/CSV files/sell_prices.csv'), delim = ",", col_types = cols())
calendar <- read_csv(str_c('/Coursework/Timeseries/Timeseries_project/CSV files/calendar.csv'), col_types = cols())

sample_submit <- vroom(str_c('/Coursework/Timeseries/Timeseries_project/CSV files/sample_submission.csv'), delim = ",", col_types = cols())

extract_ts <- function(df){
  
  min_date <- as.Date("2011-01-29")
  
  df %>%
    select(id, starts_with("d_")) %>%  
    pivot_longer(starts_with("d_"), names_to = "dates", values_to = "sales") %>%
    mutate(dates = as.integer(str_remove(dates, "d_"))) %>% 
    mutate(dates = min_date + dates - 1) %>% 
    mutate(id = str_remove(id, "_validation"))
}

set.seed(4321)
foo <- train %>% 
  sample_n(50)

ts_out <- extract_ts(foo)

cols <- ts_out %>% 
  distinct(id) %>% 
  mutate(cols = rep_len(brewer.pal(7, "Set2"), length.out = n_distinct(ts_out$id)))

ts_out <- ts_out %>% 
  left_join(cols, by = "id")

pal <- cols$cols %>%
   setNames(cols$id)
shared_ts <- highlight_key(ts_out)

palette(brewer.pal(9, "Set3"))

gg <- shared_ts %>% 
  ggplot(aes(dates, sales, col = id, group = id)) +
  geom_line() +
  scale_color_manual(values = pal) +
  labs(x = "Date", y = "Sales") +
  theme_tufte() +
  NULL

filter <- bscols(
  filter_select("ids", "Sales over time: Select a time series ID (remove with backspace key, navigate with arrow keys):", shared_ts, ~id, multiple = TRUE),
  ggplotly(gg, dynamicTicks = TRUE),
  widths = c(12, 12)
)
Sum of bscol width units is greater than 12
bscols(filter)
foo <- train %>% 
  summarise_at(vars(starts_with("d_")), sum) %>% 
  mutate(id = 1)

bar <- extract_ts(foo)

gg <- bar %>% 
  ggplot(aes(dates, sales)) +
  geom_line(col = "blue") +
  theme_tufte() +
  labs(x = "Date", y = "Sales", title = "All aggregate sales")

ggplotly(gg, dynamicTicks = TRUE)
foo <- train %>% 
  summarise_at(vars(starts_with("d_")), sum) %>% 
  mutate(id = 1)

bar <- extract_ts(foo)

gg <- bar %>% 
  ggplot(aes(dates, sales)) +
  geom_line(col = "blue") +
  theme_tufte() +
  labs(x = "Date", y = "Sales", title = "All aggregate sales")

ggplotly(gg, dynamicTicks = TRUE)
foo <- train %>%
  group_by(state_id) %>% 
  summarise_at(vars(starts_with("d_")), sum) %>% 
  rename(id = state_id)

bar <- extract_ts(foo) %>% 
  mutate(month = month(dates),
         year = year(dates)) %>% 
  group_by(month, year, id) %>% 
  summarise(sales = sum(sales),
            dates = min(dates)) %>% 
  ungroup() %>% 
  filter(str_detect(as.character(dates), "..-..-01")) %>% 
  filter(dates != max(dates))

gg <- bar %>% 
  ggplot(aes(dates, sales, col = id)) +
  geom_line() +
  theme_tufte() +
  labs(x = "Date", y = "Sales", title = "Monthly Sales per State")

ggplotly(gg, dynamicTicks = TRUE)
foo <- train %>%
  group_by(cat_id) %>% 
  summarise_at(vars(starts_with("d_")), sum) %>% 
  rename(id = cat_id)

bar <- train %>%
  group_by(store_id) %>% 
  summarise_at(vars(starts_with("d_")), sum) %>% 
  rename(id = store_id)

p1 <- extract_ts(foo) %>% 
  mutate(month = month(dates),
         year = year(dates)) %>% 
  group_by(month, year, id) %>% 
  summarise(sales = sum(sales),
            dates = min(dates)) %>% 
  ungroup() %>% 
  filter(str_detect(as.character(dates), "..-..-01")) %>% 
  filter(dates != max(dates)) %>% 
  ggplot(aes(dates, sales, col = id)) +
  geom_line() +
  theme_hc() +
  theme(legend.position = "none") +
  labs(title = "Sales per Category", x = "Date", y = "Sales")

p2 <- train %>% 
  count(cat_id) %>% 
  ggplot(aes(cat_id, n, fill = cat_id)) +
  geom_col() +
  theme_hc() +
  theme(legend.position = "none") +
  theme(axis.text.x = element_text(size = 7)) +
  labs(x = "", y = "", title = "Rows per Category")

p3 <- extract_ts(bar) %>% 
  mutate(month = month(dates),
         year = year(dates)) %>% 
  group_by(month, year, id) %>% 
  summarise(sales = sum(sales),
            dates = min(dates)) %>% 
  ungroup() %>% 
  filter(str_detect(as.character(dates), "..-..-01")) %>% 
  filter(dates != max(dates)) %>% 
  mutate(state_id = str_sub(id, 1, 2)) %>% 
  ggplot(aes(dates, sales, col = id)) +
  geom_line() +
  theme_hc() +
  theme(legend.position = "bottom") +
  labs(title = "Sales per Store", x = "Date", y = "Sales", col = "Store ID") +
  facet_wrap(~state_id)

layout <- "
AAB
CCC
"

p1 + p2 + p3 + plot_layout(design = layout)

min_date <- date("2011-01-29")

foo <- train %>%
  group_by(dept_id, state_id) %>% 
  summarise_at(vars(starts_with("d_")), sum) %>% 
  ungroup() %>% 
  select(ends_with("id"), starts_with("d_")) %>%  
  pivot_longer(starts_with("d_"), names_to = "dates", values_to = "sales") %>%
  mutate(dates = as.integer(str_remove(dates, "d_"))) %>% 
  mutate(dates = min_date + dates - 1)

foo %>% 
  mutate(month = month(dates),
         year = year(dates)) %>% 
  group_by(month, year, dept_id, state_id) %>% 
  summarise(sales = sum(sales),
            dates = min(dates)) %>% 
  ungroup() %>% 
  filter(str_detect(as.character(dates), "..-..-01")) %>% 
  filter(dates != max(dates)) %>% 
  ggplot(aes(dates, sales, col = dept_id)) +
  geom_line() +
  facet_grid(state_id ~ dept_id) +
  theme_tufte() +
  theme(legend.position = "none", strip.text.x = element_text(size = 8)) +
  labs(title = "Sales per Department and State", x = "Date", y = "Sales")

foo <- train %>% 
  summarise_at(vars(starts_with("d_")), sum) %>% 
  mutate(id = 1)

bar <- extract_ts(foo) %>% 
  filter(!str_detect(as.character(dates), "-12-25"))

loess_all <- predict(loess(bar$sales ~ as.integer(bar$dates - min(bar$dates)) + 1, span = 1/2, degree = 1))

bar <- bar %>% 
  mutate(loess = loess_all) %>% 
  mutate(sales_rel = sales - loess)

p1 <- bar %>% 
  ggplot(aes(dates, sales)) +
  geom_line(col = "blue", alpha = 0.5) +
  geom_line(aes(dates, loess), col = "black") +
  theme_hc() +
  labs(x = "", y = "Sales", title = "Total Sales with Smoothing Fit + Seasonality in Residuals")

p2 <- bar %>% 
  mutate(wday = wday(dates, label = TRUE, week_start = 1),
         month = month(dates, label = TRUE),
         year = year(dates)) %>% 
  group_by(wday, month, year) %>% 
  summarise(sales = sum(sales_rel)/1e3) %>%
  ggplot(aes(month, wday, fill = sales)) +
  geom_tile() +
  labs(x = "Month of the year", y = "Day of the week", fill = "Relative Sales [1k]") +
  scale_fill_distiller(palette = "Spectral") +
  theme_hc()

p1 / p2

foo <- train %>%
  group_by(store_id) %>% 
  summarise_at(vars(starts_with("d_")), sum) %>% 
  rename(id = store_id)

bar <- extract_ts(foo) %>% 
  filter(!str_detect(as.character(dates), "-12-25")) %>% 
  group_by(id) %>% 
  mutate(loess = predict(loess(sales ~ as.integer(dates - min(dates)) + 1, span = 1/2, degree = 1)),
         mean_sales = (sales)) %>% 
  mutate(sales_rel = (sales - loess)/mean_sales)

p1 <- bar %>% 
  ggplot(aes(dates, sales, col = id)) +
  geom_line() +
  geom_line(aes(dates, loess), col = "black") +
  facet_wrap(~ id) +
  theme_tufte() +
  theme(legend.position = "none") +
  labs(x = "", y = "Sales", title = "Sales per State with Seasonalities")
idx.CA.1=which(bar$id %in% 'CA_1')
idx.CA.2=which(bar$id %in% 'CA_2')
idx.CA.3=which(bar$id %in% 'CA_3')
idx.CA.4=which(bar$id %in% 'CA_4')

idx.WI.1=which(bar$id %in% 'WI_1')
idx.WI.2=which(bar$id %in% 'WI_2')
idx.WI.3=which(bar$id %in% 'WI_3')

idx.TX.1=which(bar$id %in% 'TX_1')
idx.TX.2=which(bar$id %in% 'TX_2')
idx.TX.3=which(bar$id %in% 'TX_3')

Cal.1<-bar$mean_sales[idx.CA.1]
Cal.2<-bar$mean_sales[idx.CA.2]
Cal.3<-bar$mean_sales[idx.CA.3]
Cal.4<-bar$mean_sales[idx.CA.4]
Cal.1.ts<-ts(Cal.1,start=1,freq=7)
Cal.2.ts<-ts(Cal.2,start=1,freq=7)
Cal.3.ts<-ts(Cal.3,start=1,freq=7)
Cal.4.ts<-ts(Cal.4,start=1,freq=7)
Cal.tot.ts=Cal.1.ts+Cal.2.ts+Cal.3.ts+Cal.4.ts


WI.1<-bar$mean_sales[idx.WI.1]
WI.2<-bar$mean_sales[idx.WI.2]
WI.3<-bar$mean_sales[idx.WI.3]
WI.1.ts<-ts(WI.1,start=1,freq=7)
WI.2.ts<-ts(WI.2,start=1,freq=7)
WI.3.ts<-ts(WI.3,start=1,freq=7)
WI.tot.ts=WI.1.ts+WI.2.ts+WI.3.ts


TX.1<-bar$mean_sales[idx.TX.1]
TX.2<-bar$mean_sales[idx.TX.2]
TX.3<-bar$mean_sales[idx.TX.3]
TX.1.ts<-ts(TX.1,start=1,freq=7)
TX.2.ts<-ts(TX.2,start=1,freq=7)
TX.3.ts<-ts(TX.3,start=1,freq=7)
TX.tot.ts=TX.1.ts+TX.2.ts+TX.3.ts

Wal.tot.ts=Cal.tot.ts+WI.tot.ts+TX.tot.ts

par(mfrow=c(1,3))
plot(Cal.tot.ts,xlab="Time (in weeks)")
plot(WI.tot.ts,xlab="Time (in weeks)")
plot(TX.tot.ts,xlab="Time (in weeks)")


require(dlm)

# Calts<-bar$mean_sales[1:1908]
# WIts<-bar$mean_sales[1909:3816]
# TXts<-bar$mean_sales[3817:5724]
# 
# CA.ts <- ts(Calts,start=1,freq=7)
# WI.ts <- ts(WIts,start=1,freq=7)
# TX.ts <- ts(TXts,start=1,freq=7)

{r} # library(dplyr) # wal <-read.csv(file='sales_train_validation.csv') # dt<-apply(wal, 1, function(r) any(r %in% c("CA"))) # Caldatachk<-as.matrix(wal[dt,7:1919]) # Calts<- colSums(Caldatachk) # dim(Calts) # Cal.ts <- ts(Calts,start=1,freq=7) #

{r} # dt2<-apply(wal, 1, function(r) any(r %in% c("TX"))) # sv<-as.matrix(wal[dt2,7:1919]) # TXdata<- colSums(sv) # TX.ts <- ts(TXdata,start=1,freq=7) # #

```{r}

dt3<-apply(wal, 1, function(r) any(r %in% c(“WI”)))

WIdata<- colSums(as.matrix(wal[dt3,7:1919]))

WI.ts <- ts(WIdata,start=1,freq=7)

plot(WI.ts,xlab=“Time (in days)”)

The three time series for each of the states are represented as above, it clearly shows seasonality, with the christmas day have zero sales. We need to provide such extra bit of information(but how?)

The combined time series shows heavy seasonality as well.



log.CA.ts=log((Wal.tot.ts))
plot(log.CA.ts)


log.WI.ts=sqrt(WI.tot.ts)
plot(log.WI.ts)


log.TX.ts=sqrt(TX.tot.ts)
plot(log.TX.ts)

NA
NA

(AKSHAT), look this chunk of code.

# DLM with polynomial second-order trend and seasonality modeled with a seasonal factor representation.
build <- function(parm) {
  dlmModPoly(order = 2, dV = exp(parm[1]), dW = c(exp(parm[2]),exp(parm[3]))) + dlmModTrig(s = 7, dV = 0, dW=exp(parm[4]))+dlmModTrig(s = 30,q=5, dV = 0, dW=exp(parm[5]))+dlmModTrig(s = 365,q=1, dV = 0, dW=exp(parm[6]))
}
fit <- dlmMLE(log.CA.ts, rep(0,6), build)
fit$convergence
[1] 0
BIC.2nd.seasfactor <-  2 *  fit$value + length(fit$par) * log(length(log.CA.ts))
print("BIC")
[1] "BIC"
BIC.2nd.seasfactor
[1] -7277.368
model2 <- build(fit$par)  #This is part where he takes the model parameters
print("Observational noise from MLE")
[1] "Observational noise from MLE"
model2$V
            [,1]
[1,] 0.003208416
print("Innovation variance matrix diagonal elements from MLE")
[1] "Innovation variance matrix diagonal elements from MLE"
model2$W[1:2,1:2]
             [,1]         [,2]
[1,] 6.683947e-05 0.000000e+00
[2,] 0.000000e+00 1.071542e-18
log.CA.filt2 <- dlmFilter(log.CA.ts, model2)

cov.filt <- with(log.CA.filt2, dlmSvd2var(U.C, D.C))

seas.term = 2

sd.seasonality.filt2 <- rep(NA,length(cov.filt))
for(i in 1:length(cov.filt)) sd.seasonality.filt2[i] = sqrt(cov.filt[[i]][seas.term,seas.term])
sd.seasonality.filt2 = ts(sd.seasonality.filt2[-(1:8)],frequency=7)
seasonality.filt2 = ts(log.CA.filt2$m[-(1:8),seas.term],frequency=7)
ll = seasonality.filt2 - 1.96 * sd.seasonality.filt2
ul = seasonality.filt2 + 1.96 * sd.seasonality.filt2
llim = min(ll)
ulim = max(ul)
plot(seasonality.filt2,ylim=c(llim,ulim))
lines(ll,lty=2,col="green")
lines(ul,lty=2,col="green")

llim = min(c(min(seasonality.filt2/sd.seasonality.filt2),-1.96))
ulim = max(c(max(seasonality.filt2/sd.seasonality.filt2),1.96))
plot(seasonality.filt2/sd.seasonality.filt2,ylim=c(llim,ulim))
abline(h=1.96,lty=2)
abline(h=-1.96,lty=2)


seas.term = 4

sd.seasonality.filt2 <- rep(NA,length(cov.filt))
for(i in 1:length(cov.filt)) sd.seasonality.filt2[i] = sqrt(cov.filt[[i]][seas.term,seas.term])
sd.seasonality.filt2 = ts(sd.seasonality.filt2[-(1:8)],frequency=7)
seasonality.filt2 = ts(log.CA.filt2$m[-(1:8),seas.term],frequency=7)
ll = seasonality.filt2 - 1.96 * sd.seasonality.filt2
ul = seasonality.filt2 + 1.96 * sd.seasonality.filt2
llim = min(ll)
ulim = max(ul)
plot(seasonality.filt2,ylim=c(llim,ulim))
lines(ll,lty=2,col="green")
lines(ul,lty=2,col="green")

llim = min(c(min(seasonality.filt2/sd.seasonality.filt2),-1.96))
ulim = max(c(max(seasonality.filt2/sd.seasonality.filt2),1.96))
plot(seasonality.filt2/sd.seasonality.filt2,ylim=c(llim,ulim))
abline(h=1.96,lty=2)
abline(h=-1.96,lty=2)




seas.term = 6

sd.seasonality.filt2 <- rep(NA,length(cov.filt))
for(i in 1:length(cov.filt)) sd.seasonality.filt2[i] = sqrt(cov.filt[[i]][seas.term,seas.term])
sd.seasonality.filt2 = ts(sd.seasonality.filt2[-(1:8)],frequency=7)
seasonality.filt2 = ts(log.CA.filt2$m[-(1:8),seas.term],frequency=7)
ll = seasonality.filt2 - 1.96 * sd.seasonality.filt2
ul = seasonality.filt2 + 1.96 * sd.seasonality.filt2
llim = min(ll)
ulim = max(ul)
plot(seasonality.filt2,ylim=c(llim,ulim))
lines(ll,lty=2,col="green")
lines(ul,lty=2,col="green")

llim = min(c(min(seasonality.filt2/sd.seasonality.filt2),-1.96))
ulim = max(c(max(seasonality.filt2/sd.seasonality.filt2),1.96))
plot(seasonality.filt2/sd.seasonality.filt2,ylim=c(llim,ulim))
abline(h=1.96,lty=2)
abline(h=-1.96,lty=2)



seas.term = 8

sd.seasonality.filt2 <- rep(NA,length(cov.filt))
for(i in 1:length(cov.filt)) sd.seasonality.filt2[i] = sqrt(cov.filt[[i]][seas.term,seas.term])
sd.seasonality.filt2 = ts(sd.seasonality.filt2[-(1:8)],frequency=7)
seasonality.filt2 = ts(log.CA.filt2$m[-(1:8),seas.term],frequency=7)
ll = seasonality.filt2 - 1.96 * sd.seasonality.filt2
ul = seasonality.filt2 + 1.96 * sd.seasonality.filt2
llim = min(ll)
ulim = max(ul)
plot(seasonality.filt2,ylim=c(llim,ulim))
lines(ll,lty=2,col="green")
lines(ul,lty=2,col="green")

llim = min(c(min(seasonality.filt2/sd.seasonality.filt2),-1.96))
ulim = max(c(max(seasonality.filt2/sd.seasonality.filt2),1.96))
plot(seasonality.filt2/sd.seasonality.filt2,ylim=c(llim,ulim))
abline(h=1.96,lty=2)
abline(h=-1.96,lty=2)






###################
#   Forecasting   #
###################

predictions <- dlmForecast(log.CA.filt2, n=28)

ll = predictions$f - 1.96 * sqrt(unlist(predictions$Q))
ul = predictions$f + 1.96 * sqrt(unlist(predictions$Q))
plot(log.CA.ts, xlab = "", col = "darkgrey",xlim=c(250,300),lwd=2)
#plot(log.choc, xlab = "", col = "darkgrey",xlim=c(1958,2000), ylim=c(1000,10000),lwd=2)
lines(predictions$f, col="red",lwd=2)
lines(ll,lty=2, col="green",lwd=2)
lines(ul,lty=2, col="green",lwd=2)


######################################################
#          One-step ahead forecast error for the last 9 years                #
######################################################
print(" Mean absolute forecast error")
[1] " Mean absolute forecast error"
# Mean absolute forecast error (MAE)
mean(abs(log.CA.filt2$f[1800:1908] - log.CA.ts[1800:1908]))
[1] 0.05948065
print(" Mean squared forecast error (MSE)")
[1] " Mean squared forecast error (MSE)"
# Mean squared forecast error (MSE)
mean((log.CA.filt2$f[1800:1908] - log.CA.ts[1800:1908])^2)
[1] 0.006213475
print(" Mean absolute percentage forecast error (MAPE)")
[1] " Mean absolute percentage forecast error (MAPE)"
# Mean absolute percentage forecast error (MAPE)
mean(abs(log.CA.filt2$f[1800:1908] - log.CA.ts[1800:1908]) / log.CA.ts[1800:1908])
[1] 0.005598321
plot(log.CA.filt2$f,ylim=c(8,12))
lines(log.CA.ts,col="green")

# Following snippet of ccode is for model diagonstics
# Get one-step ahead forecast errors
res <- residuals(log.CA.filt2, sd=FALSE)

# Plot one-step ahead forecast errors

plot(res,type='h'); abline(h=0)
par(mfrow=c(1,2))

acf(res,lag.max = 260)
pacf(res,lag.max = 260)


# Plot qq-plot of one-step ahead forecast errors
qqnorm(res); qqline(res)



# Test normality with the Shapiro-Wilk normality test
# H_0: errors are normally distribution
# H_A: errors are not normally distribution
shapiro.test(res)

    Shapiro-Wilk normality test

data:  res
W = 0.96511, p-value < 2.2e-16
# Test autocorrelation with the Ljung-Box test
# H_0: errors are independent
# H_A: errors exhibit serial correlation
 Box.test(res, lag=20, type="Ljung")   

    Box-Ljung test

data:  res
X-squared = 95.014, df = 20, p-value = 9.723e-12
sapply(1 : 20, function(i)
       Box.test(res, lag = i, type = "Ljung-Box")$p.value)
 [1] 1.233522e-06 9.946891e-10 9.663759e-11 3.415525e-10
 [5] 8.630086e-10 6.781020e-12 7.627676e-12 1.570966e-13
 [9] 2.529088e-13 7.372991e-13 9.876544e-13 2.057465e-12
[13] 5.551892e-12 7.856715e-12 1.892264e-11 4.489142e-11
[17] 8.485157e-11 1.857294e-10 1.818690e-11 9.723111e-12
# DLM with polynomial second-order trend and seasonality modeled with a seasonal factor representation.
build <- function(parm) {
  dlmModPoly(order = 2, dV = exp(parm[1]), dW = c(exp(parm[2]),exp(parm[3]))) + dlmModTrig(s = 7, dV = 0, dW=exp(parm[4]))
}
fit <- dlmMLE(log.WI.ts, rep(0,4), build)
fit$convergence
[1] 0
BIC.2nd.seasfactor <-  2 *  fit$value + length(fit$par) * log(length(log.WI.ts))
print("BIC")
[1] "BIC"
BIC.2nd.seasfactor
[1] -6382.772
model.WI <- build(fit$par)  #This is part where he takes the model parameters
print("Observational noise from MLE")
[1] "Observational noise from MLE"
model.WI$V
            [,1]
[1,] 0.007059662
print("Innovation variance matrix diagonal elements from MLE")
[1] "Innovation variance matrix diagonal elements from MLE"
model.WI$W[1:2,1:2]
             [,1]         [,2]
[1,] 0.0001928866 0.000000e+00
[2,] 0.0000000000 1.012899e-13
log.WI.filt2 <- dlmFilter(log.WI.ts, model.WI)

cov.filt <- with(log.WI.filt2, dlmSvd2var(U.C, D.C))

seas.term = 2

sd.seasonality.filt2 <- rep(NA,length(cov.filt))
for(i in 1:length(cov.filt)) sd.seasonality.filt2[i] = sqrt(cov.filt[[i]][seas.term,seas.term])
sd.seasonality.filt2 = ts(sd.seasonality.filt2[-(1:8)],frequency=7)
seasonality.filt2 = ts(log.WI.filt2$m[-(1:8),seas.term],frequency=7)
ll = seasonality.filt2 - 1.96 * sd.seasonality.filt2
ul = seasonality.filt2 + 1.96 * sd.seasonality.filt2
llim = min(ll)
ulim = max(ul)
plot(seasonality.filt2,ylim=c(llim,ulim))
lines(ll,lty=2,col="green")
lines(ul,lty=2,col="green")

llim = min(c(min(seasonality.filt2/sd.seasonality.filt2),-1.96))
ulim = max(c(max(seasonality.filt2/sd.seasonality.filt2),1.96))
plot(seasonality.filt2/sd.seasonality.filt2,ylim=c(llim,ulim))
abline(h=1.96,lty=2)
abline(h=-1.96,lty=2)


seas.term = 4

sd.seasonality.filt2 <- rep(NA,length(cov.filt))
for(i in 1:length(cov.filt)) sd.seasonality.filt2[i] = sqrt(cov.filt[[i]][seas.term,seas.term])
sd.seasonality.filt2 = ts(sd.seasonality.filt2[-(1:8)],frequency=7)
seasonality.filt2 = ts(log.WI.filt2$m[-(1:8),seas.term],frequency=7)
ll = seasonality.filt2 - 1.96 * sd.seasonality.filt2
ul = seasonality.filt2 + 1.96 * sd.seasonality.filt2
llim = min(ll)
ulim = max(ul)
plot(seasonality.filt2,ylim=c(llim,ulim))
lines(ll,lty=2,col="green")
lines(ul,lty=2,col="green")

llim = min(c(min(seasonality.filt2/sd.seasonality.filt2),-1.96))
ulim = max(c(max(seasonality.filt2/sd.seasonality.filt2),1.96))
plot(seasonality.filt2/sd.seasonality.filt2,ylim=c(llim,ulim))
abline(h=1.96,lty=2)
abline(h=-1.96,lty=2)




seas.term = 6

sd.seasonality.filt2 <- rep(NA,length(cov.filt))
for(i in 1:length(cov.filt)) sd.seasonality.filt2[i] = sqrt(cov.filt[[i]][seas.term,seas.term])
sd.seasonality.filt2 = ts(sd.seasonality.filt2[-(1:8)],frequency=7)
seasonality.filt2 = ts(log.WI.filt2$m[-(1:8),seas.term],frequency=7)
ll = seasonality.filt2 - 1.96 * sd.seasonality.filt2
ul = seasonality.filt2 + 1.96 * sd.seasonality.filt2
llim = min(ll)
ulim = max(ul)
plot(seasonality.filt2,ylim=c(llim,ulim))
lines(ll,lty=2,col="green")
lines(ul,lty=2,col="green")

llim = min(c(min(seasonality.filt2/sd.seasonality.filt2),-1.96))
ulim = max(c(max(seasonality.filt2/sd.seasonality.filt2),1.96))
plot(seasonality.filt2/sd.seasonality.filt2,ylim=c(llim,ulim))
abline(h=1.96,lty=2)
abline(h=-1.96,lty=2)



seas.term = 8

sd.seasonality.filt2 <- rep(NA,length(cov.filt))
for(i in 1:length(cov.filt)) sd.seasonality.filt2[i] = sqrt(cov.filt[[i]][seas.term,seas.term])
sd.seasonality.filt2 = ts(sd.seasonality.filt2[-(1:8)],frequency=7)
seasonality.filt2 = ts(log.WI.filt2$m[-(1:8),seas.term],frequency=7)
ll = seasonality.filt2 - 1.96 * sd.seasonality.filt2
ul = seasonality.filt2 + 1.96 * sd.seasonality.filt2
llim = min(ll)
ulim = max(ul)
plot(seasonality.filt2,ylim=c(llim,ulim))
lines(ll,lty=2,col="green")
lines(ul,lty=2,col="green")

llim = min(c(min(seasonality.filt2/sd.seasonality.filt2),-1.96))
ulim = max(c(max(seasonality.filt2/sd.seasonality.filt2),1.96))
plot(seasonality.filt2/sd.seasonality.filt2,ylim=c(llim,ulim))
abline(h=1.96,lty=2)
abline(h=-1.96,lty=2)






###################
#   Forecasting   #
###################

predictions <- dlmForecast(log.WI.filt2, n=28)

ll = predictions$f - 1.96 * sqrt(unlist(predictions$Q))
ul = predictions$f + 1.96 * sqrt(unlist(predictions$Q))
plot(log.WI.ts, xlab = "", col = "darkgrey",xlim=c(250,300),lwd=2)
#plot(log.choc, xlab = "", col = "darkgrey",xlim=c(1958,2000), ylim=c(1000,10000),lwd=2)
lines(predictions$f, col="red",lwd=2)
lines(ll,lty=2, col="green",lwd=2)
lines(ul,lty=2, col="green",lwd=2)


######################################################
#          One-step ahead forecast error for the last 9 years                #
######################################################
print(" Mean absolute forecast error")
[1] " Mean absolute forecast error"
# Mean absolute forecast error (MAE)
mean(abs(log.WI.filt2$f[1800:1908] - log.WI.ts[1800:1908]))
[1] 0.09760941
print(" Mean squared forecast error (MSE)")
[1] " Mean squared forecast error (MSE)"
# Mean squared forecast error (MSE)
mean((log.WI.filt2$f[1800:1908] - log.WI.ts[1800:1908])^2)
[1] 0.02638784
print(" Mean absolute percentage forecast error (MAPE)")
[1] " Mean absolute percentage forecast error (MAPE)"
# Mean absolute percentage forecast error (MAPE)
mean(abs(log.WI.filt2$f[1800:1908] - log.WI.ts[1800:1908]) / log.WI.ts[1800:1908])
[1] 0.01176742
plot(log.WI.filt2$f,ylim=c(9,11))
lines(log.WI.ts,col="green")

NA
NA
# Following snippet of ccode is for model diagonstics
# Get one-step ahead forecast errors
res <- residuals(log.WI.filt2, sd=FALSE)

# Plot one-step ahead forecast errors

plot(res,type='h'); abline(h=0)
par(mfrow=c(1,2))

acf(res,lag.max = 260)
pacf(res,lag.max = 260)


# Plot qq-plot of one-step ahead forecast errors
qqnorm(res); qqline(res)



# Test normality with the Shapiro-Wilk normality test
# H_0: errors are normally distribution
# H_A: errors are not normally distribution
shapiro.test(res)

    Shapiro-Wilk normality test

data:  res
W = 0.92541, p-value < 2.2e-16
# Test autocorrelation with the Ljung-Box test
# H_0: errors are independent
# H_A: errors exhibit serial correlation
 Box.test(res, lag=20, type="Ljung")   

    Box-Ljung test

data:  res
X-squared = 125.17, df = 20, p-value < 2.2e-16
sapply(1 : 20, function(i)
       Box.test(res, lag = i, type = "Ljung-Box")$p.value)
 [1] 9.274980e-09 4.651535e-08 4.268566e-08 1.322641e-10 9.722334e-12 3.068412e-11 4.985268e-11 3.441691e-15 1.010303e-14 6.550316e-15
[11] 1.887379e-15 1.110223e-16 2.220446e-16 2.220446e-16 0.000000e+00 0.000000e+00 0.000000e+00 1.110223e-16 0.000000e+00 0.000000e+00
build <- function(parm) {
  dlmModPoly(order = 2, dV = exp(parm[1]), dW = c(exp(parm[2]),exp(parm[3]))) + dlmModTrig(s = 7, dV = 0, dW=exp(parm[4]))
}
fit <- dlmMLE(log.TX.ts, rep(0,4), build)
fit$convergence
[1] 0
BIC.2nd.seasfactor <-  2 *  fit$value + length(fit$par) * log(length(log.TX.ts))
print("BIC")
[1] "BIC"
BIC.2nd.seasfactor
[1] -6774.413
model.TX<- build(fit$par)  #This is part where he takes the model parameters
print("Observational noise from MLE")
[1] "Observational noise from MLE"
model.TX$V
            [,1]
[1,] 0.004209568
print("Innovation variance matrix diagonal elements from MLE")
[1] "Innovation variance matrix diagonal elements from MLE"
model.TX$W[1:2,1:2]
            [,1]         [,2]
[1,] 0.001404132 0.000000e+00
[2,] 0.000000000 4.036832e-14
log.TX.filt2 <- dlmFilter(log.TX.ts, model.TX)

cov.filt <- with(log.TX.filt2, dlmSvd2var(U.C, D.C))

seas.term = 2

sd.seasonality.filt2 <- rep(NA,length(cov.filt))
for(i in 1:length(cov.filt)) sd.seasonality.filt2[i] = sqrt(cov.filt[[i]][seas.term,seas.term])
sd.seasonality.filt2 = ts(sd.seasonality.filt2[-(1:8)],frequency=7)
seasonality.filt2 = ts(log.TX.filt2$m[-(1:8),seas.term],frequency=7)
ll = seasonality.filt2 - 1.96 * sd.seasonality.filt2
ul = seasonality.filt2 + 1.96 * sd.seasonality.filt2
llim = min(ll)
ulim = max(ul)
plot(seasonality.filt2,ylim=c(llim,ulim))
lines(ll,lty=2,col="green")
lines(ul,lty=2,col="green")

llim = min(c(min(seasonality.filt2/sd.seasonality.filt2),-1.96))
ulim = max(c(max(seasonality.filt2/sd.seasonality.filt2),1.96))
plot(seasonality.filt2/sd.seasonality.filt2,ylim=c(llim,ulim))
abline(h=1.96,lty=2)
abline(h=-1.96,lty=2)


seas.term = 4

sd.seasonality.filt2 <- rep(NA,length(cov.filt))
for(i in 1:length(cov.filt)) sd.seasonality.filt2[i] = sqrt(cov.filt[[i]][seas.term,seas.term])
sd.seasonality.filt2 = ts(sd.seasonality.filt2[-(1:8)],frequency=7)
seasonality.filt2 = ts(log.TX.filt2$m[-(1:8),seas.term],frequency=7)
ll = seasonality.filt2 - 1.96 * sd.seasonality.filt2
ul = seasonality.filt2 + 1.96 * sd.seasonality.filt2
llim = min(ll)
ulim = max(ul)
plot(seasonality.filt2,ylim=c(llim,ulim))
lines(ll,lty=2,col="green")
lines(ul,lty=2,col="green")

llim = min(c(min(seasonality.filt2/sd.seasonality.filt2),-1.96))
ulim = max(c(max(seasonality.filt2/sd.seasonality.filt2),1.96))
plot(seasonality.filt2/sd.seasonality.filt2,ylim=c(llim,ulim))
abline(h=1.96,lty=2)
abline(h=-1.96,lty=2)




seas.term = 6

sd.seasonality.filt2 <- rep(NA,length(cov.filt))
for(i in 1:length(cov.filt)) sd.seasonality.filt2[i] = sqrt(cov.filt[[i]][seas.term,seas.term])
sd.seasonality.filt2 = ts(sd.seasonality.filt2[-(1:8)],frequency=7)
seasonality.filt2 = ts(log.TX.filt2$m[-(1:8),seas.term],frequency=7)
ll = seasonality.filt2 - 1.96 * sd.seasonality.filt2
ul = seasonality.filt2 + 1.96 * sd.seasonality.filt2
llim = min(ll)
ulim = max(ul)
plot(seasonality.filt2,ylim=c(llim,ulim))
lines(ll,lty=2,col="green")
lines(ul,lty=2,col="green")

llim = min(c(min(seasonality.filt2/sd.seasonality.filt2),-1.96))
ulim = max(c(max(seasonality.filt2/sd.seasonality.filt2),1.96))
plot(seasonality.filt2/sd.seasonality.filt2,ylim=c(llim,ulim))
abline(h=1.96,lty=2)
abline(h=-1.96,lty=2)



seas.term = 8

sd.seasonality.filt2 <- rep(NA,length(cov.filt))
for(i in 1:length(cov.filt)) sd.seasonality.filt2[i] = sqrt(cov.filt[[i]][seas.term,seas.term])
sd.seasonality.filt2 = ts(sd.seasonality.filt2[-(1:8)],frequency=7)
seasonality.filt2 = ts(log.TX.filt2$m[-(1:8),seas.term],frequency=7)
ll = seasonality.filt2 - 1.96 * sd.seasonality.filt2
ul = seasonality.filt2 + 1.96 * sd.seasonality.filt2
llim = min(ll)
ulim = max(ul)
plot(seasonality.filt2,ylim=c(llim,ulim))
lines(ll,lty=2,col="green")
lines(ul,lty=2,col="green")

llim = min(c(min(seasonality.filt2/sd.seasonality.filt2),-1.96))
ulim = max(c(max(seasonality.filt2/sd.seasonality.filt2),1.96))
plot(seasonality.filt2/sd.seasonality.filt2,ylim=c(llim,ulim))
abline(h=1.96,lty=2)
abline(h=-1.96,lty=2)






###################
#   Forecasting   #
###################

predictions <- dlmForecast(log.TX.filt2, n=28)

ll = predictions$f - 1.96 * sqrt(unlist(predictions$Q))
ul = predictions$f + 1.96 * sqrt(unlist(predictions$Q))
plot(log.TX.ts, xlab = "", col = "darkgrey",xlim=c(250,300),lwd=2)
#plot(log.choc, xlab = "", col = "darkgrey",xlim=c(1958,2000), ylim=c(1000,10000),lwd=2)
lines(predictions$f, col="red",lwd=2)
lines(ll,lty=2, col="green",lwd=2)
lines(ul,lty=2, col="green",lwd=2)


######################################################
#          One-step ahead forecast error for the last 9 years                #
######################################################
print(" Mean absolute forecast error")
[1] " Mean absolute forecast error"
# Mean absolute forecast error (MAE)
mean(abs(log.TX.filt2$f[1800:1908] - log.TX.ts[1800:1908]))
[1] 0.06367577
print(" Mean squared forecast error (MSE)")
[1] " Mean squared forecast error (MSE)"
# Mean squared forecast error (MSE)
mean((log.WI.filt2$f[1800:1908] - log.WI.ts[1800:1908])^2)
[1] 0.02638784
print(" Mean absolute percentage forecast error (MAPE)")
[1] " Mean absolute percentage forecast error (MAPE)"
# Mean absolute percentage forecast error (MAPE)
mean(abs(log.WI.filt2$f[1800:1908] - log.WI.ts[1800:1908]) / log.WI.ts[1800:1908])
[1] 0.01176742
plot(log.WI.filt2$f,ylim=c(8,10))
lines(log.WI.ts,col="green")

# Following snippet of ccode is for model diagonstics
# Get one-step ahead forecast errors
res <- residuals(log.TX.filt2, sd=FALSE)

# Plot one-step ahead forecast errors

plot(res,type='h'); abline(h=0)
par(mfrow=c(1,2))

acf(res,lag.max = 260)
pacf(res,lag.max = 260)


# Plot qq-plot of one-step ahead forecast errors
qqnorm(res); qqline(res)



# Test normality with the Shapiro-Wilk normality test
# H_0: errors are normally distribution
# H_A: errors are not normally distribution
shapiro.test(res)

    Shapiro-Wilk normality test

data:  res
W = 0.96155, p-value < 2.2e-16
# Test autocorrelation with the Ljung-Box test
# H_0: errors are independent
# H_A: errors exhibit serial correlation
 Box.test(res, lag=20, type="Ljung")   

    Box-Ljung test

data:  res
X-squared = 176.66, df = 20, p-value < 2.2e-16
sapply(1 : 20, function(i)
       Box.test(res, lag = i, type = "Ljung-Box")$p.value)
 [1] 1.380142e-08 1.718238e-10 1.110223e-16 0.000000e+00 0.000000e+00 0.000000e+00 0.000000e+00 0.000000e+00 0.000000e+00 0.000000e+00
[11] 0.000000e+00 0.000000e+00 0.000000e+00 0.000000e+00 0.000000e+00 0.000000e+00 0.000000e+00 0.000000e+00 0.000000e+00 0.000000e+00

log.TX.filt2 <- function(newts){
remove(log.TX.ts)
build <- function(parm) {
  dlmModPoly(order = 2, dV = exp(parm[1]), dW = c(exp(parm[2]),exp(parm[3]))) + dlmModTrig(s = 7, dV = 0, dW=exp(parm[4]))
}
fit <- dlmMLE(newts, rep(0,4), build)
fit$convergence

BIC.2nd.seasfactor <-  2 *  fit$value + length(fit$par) * log(length(newts))
print("BIC")
BIC.2nd.seasfactor

model.TX<- build(fit$par)  #This is part where he takes the model parameters
print("Observational noise from MLE")
model.TX$V
print("Innovation variance matrix diagonal elements from MLE")
model.TX$W[1:2,1:2]

log.TX.filt2 <- dlmFilter(newts, model.TX)

cov.filt <- with(log.TX.filt2, dlmSvd2var(U.C, D.C))

seas.term = 2

sd.seasonality.filt2 <- rep(NA,length(cov.filt))
for(i in 1:length(cov.filt)) sd.seasonality.filt2[i] = sqrt(cov.filt[[i]][seas.term,seas.term])
sd.seasonality.filt2 = ts(sd.seasonality.filt2[-(1:8)],frequency=7)
seasonality.filt2 = ts(log.TX.filt2$m[-(1:8),seas.term],frequency=7)
ll = seasonality.filt2 - 1.96 * sd.seasonality.filt2
ul = seasonality.filt2 + 1.96 * sd.seasonality.filt2
llim = min(ll)
ulim = max(ul)
plot(seasonality.filt2,ylim=c(llim,ulim))
lines(ll,lty=2,col="green")
lines(ul,lty=2,col="green")
llim = min(c(min(seasonality.filt2/sd.seasonality.filt2),-1.96))
ulim = max(c(max(seasonality.filt2/sd.seasonality.filt2),1.96))
plot(seasonality.filt2/sd.seasonality.filt2,ylim=c(llim,ulim))
abline(h=1.96,lty=2)
abline(h=-1.96,lty=2)

seas.term = 4

sd.seasonality.filt2 <- rep(NA,length(cov.filt))
for(i in 1:length(cov.filt)) sd.seasonality.filt2[i] = sqrt(cov.filt[[i]][seas.term,seas.term])
sd.seasonality.filt2 = ts(sd.seasonality.filt2[-(1:8)],frequency=7)
seasonality.filt2 = ts(log.TX.filt2$m[-(1:8),seas.term],frequency=7)
ll = seasonality.filt2 - 1.96 * sd.seasonality.filt2
ul = seasonality.filt2 + 1.96 * sd.seasonality.filt2
llim = min(ll)
ulim = max(ul)
plot(seasonality.filt2,ylim=c(llim,ulim))
lines(ll,lty=2,col="green")
lines(ul,lty=2,col="green")
llim = min(c(min(seasonality.filt2/sd.seasonality.filt2),-1.96))
ulim = max(c(max(seasonality.filt2/sd.seasonality.filt2),1.96))
plot(seasonality.filt2/sd.seasonality.filt2,ylim=c(llim,ulim))
abline(h=1.96,lty=2)
abline(h=-1.96,lty=2)



seas.term = 6

sd.seasonality.filt2 <- rep(NA,length(cov.filt))
for(i in 1:length(cov.filt)) sd.seasonality.filt2[i] = sqrt(cov.filt[[i]][seas.term,seas.term])
sd.seasonality.filt2 = ts(sd.seasonality.filt2[-(1:8)],frequency=7)
seasonality.filt2 = ts(log.TX.filt2$m[-(1:8),seas.term],frequency=7)
ll = seasonality.filt2 - 1.96 * sd.seasonality.filt2
ul = seasonality.filt2 + 1.96 * sd.seasonality.filt2
llim = min(ll)
ulim = max(ul)
plot(seasonality.filt2,ylim=c(llim,ulim))
lines(ll,lty=2,col="green")
lines(ul,lty=2,col="green")
llim = min(c(min(seasonality.filt2/sd.seasonality.filt2),-1.96))
ulim = max(c(max(seasonality.filt2/sd.seasonality.filt2),1.96))
plot(seasonality.filt2/sd.seasonality.filt2,ylim=c(llim,ulim))
abline(h=1.96,lty=2)
abline(h=-1.96,lty=2)


seas.term = 8

sd.seasonality.filt2 <- rep(NA,length(cov.filt))
for(i in 1:length(cov.filt)) sd.seasonality.filt2[i] = sqrt(cov.filt[[i]][seas.term,seas.term])
sd.seasonality.filt2 = ts(sd.seasonality.filt2[-(1:8)],frequency=7)
seasonality.filt2 = ts(log.TX.filt2$m[-(1:8),seas.term],frequency=7)
ll = seasonality.filt2 - 1.96 * sd.seasonality.filt2
ul = seasonality.filt2 + 1.96 * sd.seasonality.filt2
llim = min(ll)
ulim = max(ul)
plot(seasonality.filt2,ylim=c(llim,ulim))
lines(ll,lty=2,col="green")
lines(ul,lty=2,col="green")
llim = min(c(min(seasonality.filt2/sd.seasonality.filt2),-1.96))
ulim = max(c(max(seasonality.filt2/sd.seasonality.filt2),1.96))
plot(seasonality.filt2/sd.seasonality.filt2,ylim=c(llim,ulim))
abline(h=1.96,lty=2)
abline(h=-1.96,lty=2)





###################
#   Forecasting   #
###################

predictions <- dlmForecast(log.TX.filt2, n=28)

ll = predictions$f - 1.96 * sqrt(unlist(predictions$Q))
ul = predictions$f + 1.96 * sqrt(unlist(predictions$Q))
plot(newts, xlab = "", col = "darkgrey",xlim=c(250,300),lwd=2)
#plot(log.choc, xlab = "", col = "darkgrey",xlim=c(1958,2000), ylim=c(1000,10000),lwd=2)
lines(predictions$f, col="red",lwd=2)
lines(ll,lty=2, col="green",lwd=2)
lines(ul,lty=2, col="green",lwd=2)

######################################################
#          One-step ahead forecast error for the last 9 years                #
######################################################
print(" Mean absolute forecast error")
# Mean absolute forecast error (MAE)
mean(abs(log.TX.filt2$f[1800:1908] - newts[1800:1908]))

print(" Mean squared forecast error (MSE)")
# Mean squared forecast error (MSE)
mean((log.TX.filt2$f[1800:1908] - newts[1800:1908])^2)

print(" Mean absolute percentage forecast error (MAPE)")
# Mean absolute percentage forecast error (MAPE)
mean(abs(log.TX.filt2$f[1800:1908] - newts[1800:1908]) / newts[1800:1908])

plot(log.TX.filt2$f,ylim=c(8,10))
lines(newts,col="green") 
}
LS0tDQp0aXRsZTogIlIgTm90ZWJvb2siDQpvdXRwdXQ6DQogIGh0bWxfZG9jdW1lbnQ6DQogICAgZGZfcHJpbnQ6IHBhZ2VkDQogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQNCiAgcGRmX2RvY3VtZW50OiBkZWZhdWx0DQotLS0NCg0KVGhpcyBpcyBhbiBbUiBNYXJrZG93bl0oaHR0cDovL3JtYXJrZG93bi5yc3R1ZGlvLmNvbSkgTm90ZWJvb2suIFdoZW4geW91IGV4ZWN1dGUgY29kZSB3aXRoaW4gdGhlIG5vdGVib29rLCB0aGUgcmVzdWx0cyBhcHBlYXIgYmVuZWF0aCB0aGUgY29kZS4gDQoNClRyeSBleGVjdXRpbmcgdGhpcyBjaHVuayBieSBjbGlja2luZyB0aGUgKlJ1biogYnV0dG9uIHdpdGhpbiB0aGUgY2h1bmsgb3IgYnkgcGxhY2luZyB5b3VyIGN1cnNvciBpbnNpZGUgaXQgYW5kIHByZXNzaW5nICpDdHJsK1NoaWZ0K0VudGVyKi4gDQoNCmBgYHtyfQ0KIyBnZW5lcmFsIHZpc3VhbGlzYXRpb24NCmxpYnJhcnkoJ2dncGxvdDInKSAjIHZpc3VhbGlzYXRpb24NCmxpYnJhcnkoJ3NjYWxlcycpICMgdmlzdWFsaXNhdGlvbg0KbGlicmFyeSgncGF0Y2h3b3JrJykgIyB2aXN1YWxpc2F0aW9uDQpsaWJyYXJ5KCdSQ29sb3JCcmV3ZXInKSAjIHZpc3VhbGlzYXRpb24NCmxpYnJhcnkoJ2NvcnJwbG90JykgIyB2aXN1YWxpc2F0aW9uDQoNCiMgZ2VuZXJhbCBkYXRhIG1hbmlwdWxhdGlvbg0KbGlicmFyeSgnZHBseXInKSAjIGRhdGEgbWFuaXB1bGF0aW9uDQpsaWJyYXJ5KCdyZWFkcicpICMgaW5wdXQvb3V0cHV0DQpsaWJyYXJ5KCd2cm9vbScpICMgaW5wdXQvb3V0cHV0DQpsaWJyYXJ5KCdza2ltcicpICMgb3ZlcnZpZXcNCmxpYnJhcnkoJ3RpYmJsZScpICMgZGF0YSB3cmFuZ2xpbmcNCmxpYnJhcnkoJ3RpZHlyJykgIyBkYXRhIHdyYW5nbGluZw0KbGlicmFyeSgncHVycnInKSAjIGRhdGEgd3JhbmdsaW5nDQpsaWJyYXJ5KCdzdHJpbmdyJykgIyBzdHJpbmcgbWFuaXB1bGF0aW9uDQpsaWJyYXJ5KCdmb3JjYXRzJykgIyBmYWN0b3IgbWFuaXB1bGF0aW9uDQoNCiMgc3BlY2lmaWMgdmlzdWFsaXNhdGlvbg0KbGlicmFyeSgnYWxsdXZpYWwnKSAjIHZpc3VhbGlzYXRpb24NCmxpYnJhcnkoJ2dncmVwZWwnKSAjIHZpc3VhbGlzYXRpb24NCmxpYnJhcnkoJ2dnZm9yY2UnKSAjIHZpc3VhbGlzYXRpb24NCmxpYnJhcnkoJ2dncmlkZ2VzJykgIyB2aXN1YWxpc2F0aW9uDQpsaWJyYXJ5KCdnZ2FuaW1hdGUnKSAjIGFuaW1hdGlvbnMNCmxpYnJhcnkoJ0dHYWxseScpICMgdmlzdWFsaXNhdGlvbg0KbGlicmFyeSgnZ2d0aGVtZXMnKSAjIHZpc3VhbGlzYXRpb24NCmxpYnJhcnkoJ3dlc2FuZGVyc29uJykgIyB2aXN1YWxpc2F0aW9uDQpsaWJyYXJ5KCdrYWJsZUV4dHJhJykgIyBkaXNwbGF5DQoNCiMgRGF0ZSArIGZvcmVjYXN0DQpsaWJyYXJ5KCdsdWJyaWRhdGUnKSAjIGRhdGUgYW5kIHRpbWUNCmxpYnJhcnkoJ2ZvcmVjYXN0JykgIyB0aW1lIHNlcmllcyBhbmFseXNpcw0KI2xpYnJhcnkoJ3Byb3BoZXQnKSAjIHRpbWUgc2VyaWVzIGFuYWx5c2lzDQpsaWJyYXJ5KCd0aW1ldGsnKSAjIHRpbWUgc2VyaWVzIGFuYWx5c2lzDQoNCiMgSW50ZXJhY3Rpdml0eQ0KbGlicmFyeSgnY3Jvc3N0YWxrJykNCmxpYnJhcnkoJ3Bsb3RseScpDQoNCiMgcGFyYWxsZWwNCmxpYnJhcnkoJ2ZvcmVhY2gnKQ0KbGlicmFyeSgnZG9QYXJhbGxlbCcpDQoNCmBgYA0KDQoNCmBgYHtyfQ0KbGlicmFyeSh2cm9vbSkNCmxpYnJhcnkoc3RyaW5ncikNCmxpYnJhcnkodGlkeXZlcnNlKQ0KdHJhaW4gPC0gdnJvb20oc3RyX2MoJy9Db3Vyc2V3b3JrL1RpbWVzZXJpZXMvVGltZXNlcmllc19wcm9qZWN0L0NTViBmaWxlcy9zYWxlc190cmFpbl92YWxpZGF0aW9uLmNzdicpLCBkZWxpbSA9ICIsIiwgY29sX3R5cGVzID0gY29scygpKQ0KcHJpY2VzIDwtIHZyb29tKHN0cl9jKCcvQ291cnNld29yay9UaW1lc2VyaWVzL1RpbWVzZXJpZXNfcHJvamVjdC9DU1YgZmlsZXMvc2VsbF9wcmljZXMuY3N2JyksIGRlbGltID0gIiwiLCBjb2xfdHlwZXMgPSBjb2xzKCkpDQpjYWxlbmRhciA8LSByZWFkX2NzdihzdHJfYygnL0NvdXJzZXdvcmsvVGltZXNlcmllcy9UaW1lc2VyaWVzX3Byb2plY3QvQ1NWIGZpbGVzL2NhbGVuZGFyLmNzdicpLCBjb2xfdHlwZXMgPSBjb2xzKCkpDQoNCnNhbXBsZV9zdWJtaXQgPC0gdnJvb20oc3RyX2MoJy9Db3Vyc2V3b3JrL1RpbWVzZXJpZXMvVGltZXNlcmllc19wcm9qZWN0L0NTViBmaWxlcy9zYW1wbGVfc3VibWlzc2lvbi5jc3YnKSwgZGVsaW0gPSAiLCIsIGNvbF90eXBlcyA9IGNvbHMoKSkNCmBgYA0KDQpgYGB7cn0NCg0KZXh0cmFjdF90cyA8LSBmdW5jdGlvbihkZil7DQogIA0KICBtaW5fZGF0ZSA8LSBhcy5EYXRlKCIyMDExLTAxLTI5IikNCiAgDQogIGRmICU+JQ0KICAgIHNlbGVjdChpZCwgc3RhcnRzX3dpdGgoImRfIikpICU+JSAgDQogICAgcGl2b3RfbG9uZ2VyKHN0YXJ0c193aXRoKCJkXyIpLCBuYW1lc190byA9ICJkYXRlcyIsIHZhbHVlc190byA9ICJzYWxlcyIpICU+JQ0KICAgIG11dGF0ZShkYXRlcyA9IGFzLmludGVnZXIoc3RyX3JlbW92ZShkYXRlcywgImRfIikpKSAlPiUgDQogICAgbXV0YXRlKGRhdGVzID0gbWluX2RhdGUgKyBkYXRlcyAtIDEpICU+JSANCiAgICBtdXRhdGUoaWQgPSBzdHJfcmVtb3ZlKGlkLCAiX3ZhbGlkYXRpb24iKSkNCn0NCg0Kc2V0LnNlZWQoNDMyMSkNCmZvbyA8LSB0cmFpbiAlPiUgDQogIHNhbXBsZV9uKDUwKQ0KDQp0c19vdXQgPC0gZXh0cmFjdF90cyhmb28pDQoNCmNvbHMgPC0gdHNfb3V0ICU+JSANCiAgZGlzdGluY3QoaWQpICU+JSANCiAgbXV0YXRlKGNvbHMgPSByZXBfbGVuKGJyZXdlci5wYWwoNywgIlNldDIiKSwgbGVuZ3RoLm91dCA9IG5fZGlzdGluY3QodHNfb3V0JGlkKSkpDQoNCnRzX291dCA8LSB0c19vdXQgJT4lIA0KICBsZWZ0X2pvaW4oY29scywgYnkgPSAiaWQiKQ0KDQpwYWwgPC0gY29scyRjb2xzICU+JQ0KICAgc2V0TmFtZXMoY29scyRpZCkNCmBgYA0KDQpgYGB7cn0NCnNoYXJlZF90cyA8LSBoaWdobGlnaHRfa2V5KHRzX291dCkNCg0KcGFsZXR0ZShicmV3ZXIucGFsKDksICJTZXQzIikpDQoNCmdnIDwtIHNoYXJlZF90cyAlPiUgDQogIGdncGxvdChhZXMoZGF0ZXMsIHNhbGVzLCBjb2wgPSBpZCwgZ3JvdXAgPSBpZCkpICsNCiAgZ2VvbV9saW5lKCkgKw0KICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gcGFsKSArDQogIGxhYnMoeCA9ICJEYXRlIiwgeSA9ICJTYWxlcyIpICsNCiAgdGhlbWVfdHVmdGUoKSArDQogIE5VTEwNCg0KZmlsdGVyIDwtIGJzY29scygNCiAgZmlsdGVyX3NlbGVjdCgiaWRzIiwgIlNhbGVzIG92ZXIgdGltZTogU2VsZWN0IGEgdGltZSBzZXJpZXMgSUQgKHJlbW92ZSB3aXRoIGJhY2tzcGFjZSBrZXksIG5hdmlnYXRlIHdpdGggYXJyb3cga2V5cyk6Iiwgc2hhcmVkX3RzLCB+aWQsIG11bHRpcGxlID0gVFJVRSksDQogIGdncGxvdGx5KGdnLCBkeW5hbWljVGlja3MgPSBUUlVFKSwNCiAgd2lkdGhzID0gYygxMiwgMTIpDQopDQoNCmJzY29scyhmaWx0ZXIpDQpgYGANCmBgYHtyfQ0KZm9vIDwtIHRyYWluICU+JSANCiAgc3VtbWFyaXNlX2F0KHZhcnMoc3RhcnRzX3dpdGgoImRfIikpLCBzdW0pICU+JSANCiAgbXV0YXRlKGlkID0gMSkNCg0KYmFyIDwtIGV4dHJhY3RfdHMoZm9vKQ0KDQpnZyA8LSBiYXIgJT4lIA0KICBnZ3Bsb3QoYWVzKGRhdGVzLCBzYWxlcykpICsNCiAgZ2VvbV9saW5lKGNvbCA9ICJibHVlIikgKw0KICB0aGVtZV90dWZ0ZSgpICsNCiAgbGFicyh4ID0gIkRhdGUiLCB5ID0gIlNhbGVzIiwgdGl0bGUgPSAiQWxsIGFnZ3JlZ2F0ZSBzYWxlcyIpDQoNCmdncGxvdGx5KGdnLCBkeW5hbWljVGlja3MgPSBUUlVFKQ0KYGBgDQpgYGB7cn0NCmZvbyA8LSB0cmFpbiAlPiUgDQogIHN1bW1hcmlzZV9hdCh2YXJzKHN0YXJ0c193aXRoKCJkXyIpKSwgc3VtKSAlPiUgDQogIG11dGF0ZShpZCA9IDEpDQoNCmJhciA8LSBleHRyYWN0X3RzKGZvbykNCg0KZ2cgPC0gYmFyICU+JSANCiAgZ2dwbG90KGFlcyhkYXRlcywgc2FsZXMpKSArDQogIGdlb21fbGluZShjb2wgPSAiYmx1ZSIpICsNCiAgdGhlbWVfdHVmdGUoKSArDQogIGxhYnMoeCA9ICJEYXRlIiwgeSA9ICJTYWxlcyIsIHRpdGxlID0gIkFsbCBhZ2dyZWdhdGUgc2FsZXMiKQ0KDQpnZ3Bsb3RseShnZywgZHluYW1pY1RpY2tzID0gVFJVRSkNCmBgYA0KYGBge3J9DQpmb28gPC0gdHJhaW4gJT4lDQogIGdyb3VwX2J5KHN0YXRlX2lkKSAlPiUgDQogIHN1bW1hcmlzZV9hdCh2YXJzKHN0YXJ0c193aXRoKCJkXyIpKSwgc3VtKSAlPiUgDQogIHJlbmFtZShpZCA9IHN0YXRlX2lkKQ0KDQpiYXIgPC0gZXh0cmFjdF90cyhmb28pICU+JSANCiAgbXV0YXRlKG1vbnRoID0gbW9udGgoZGF0ZXMpLA0KICAgICAgICAgeWVhciA9IHllYXIoZGF0ZXMpKSAlPiUgDQogIGdyb3VwX2J5KG1vbnRoLCB5ZWFyLCBpZCkgJT4lIA0KICBzdW1tYXJpc2Uoc2FsZXMgPSBzdW0oc2FsZXMpLA0KICAgICAgICAgICAgZGF0ZXMgPSBtaW4oZGF0ZXMpKSAlPiUgDQogIHVuZ3JvdXAoKSAlPiUgDQogIGZpbHRlcihzdHJfZGV0ZWN0KGFzLmNoYXJhY3RlcihkYXRlcyksICIuLi0uLi0wMSIpKSAlPiUgDQogIGZpbHRlcihkYXRlcyAhPSBtYXgoZGF0ZXMpKQ0KDQpnZyA8LSBiYXIgJT4lIA0KICBnZ3Bsb3QoYWVzKGRhdGVzLCBzYWxlcywgY29sID0gaWQpKSArDQogIGdlb21fbGluZSgpICsNCiAgdGhlbWVfdHVmdGUoKSArDQogIGxhYnMoeCA9ICJEYXRlIiwgeSA9ICJTYWxlcyIsIHRpdGxlID0gIk1vbnRobHkgU2FsZXMgcGVyIFN0YXRlIikNCg0KZ2dwbG90bHkoZ2csIGR5bmFtaWNUaWNrcyA9IFRSVUUpDQpgYGANCg0KDQoNCg0KDQpgYGB7cn0NCmZvbyA8LSB0cmFpbiAlPiUNCiAgZ3JvdXBfYnkoY2F0X2lkKSAlPiUgDQogIHN1bW1hcmlzZV9hdCh2YXJzKHN0YXJ0c193aXRoKCJkXyIpKSwgc3VtKSAlPiUgDQogIHJlbmFtZShpZCA9IGNhdF9pZCkNCg0KYmFyIDwtIHRyYWluICU+JQ0KICBncm91cF9ieShzdG9yZV9pZCkgJT4lIA0KICBzdW1tYXJpc2VfYXQodmFycyhzdGFydHNfd2l0aCgiZF8iKSksIHN1bSkgJT4lIA0KICByZW5hbWUoaWQgPSBzdG9yZV9pZCkNCg0KcDEgPC0gZXh0cmFjdF90cyhmb28pICU+JSANCiAgbXV0YXRlKG1vbnRoID0gbW9udGgoZGF0ZXMpLA0KICAgICAgICAgeWVhciA9IHllYXIoZGF0ZXMpKSAlPiUgDQogIGdyb3VwX2J5KG1vbnRoLCB5ZWFyLCBpZCkgJT4lIA0KICBzdW1tYXJpc2Uoc2FsZXMgPSBzdW0oc2FsZXMpLA0KICAgICAgICAgICAgZGF0ZXMgPSBtaW4oZGF0ZXMpKSAlPiUgDQogIHVuZ3JvdXAoKSAlPiUgDQogIGZpbHRlcihzdHJfZGV0ZWN0KGFzLmNoYXJhY3RlcihkYXRlcyksICIuLi0uLi0wMSIpKSAlPiUgDQogIGZpbHRlcihkYXRlcyAhPSBtYXgoZGF0ZXMpKSAlPiUgDQogIGdncGxvdChhZXMoZGF0ZXMsIHNhbGVzLCBjb2wgPSBpZCkpICsNCiAgZ2VvbV9saW5lKCkgKw0KICB0aGVtZV9oYygpICsNCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArDQogIGxhYnModGl0bGUgPSAiU2FsZXMgcGVyIENhdGVnb3J5IiwgeCA9ICJEYXRlIiwgeSA9ICJTYWxlcyIpDQoNCnAyIDwtIHRyYWluICU+JSANCiAgY291bnQoY2F0X2lkKSAlPiUgDQogIGdncGxvdChhZXMoY2F0X2lkLCBuLCBmaWxsID0gY2F0X2lkKSkgKw0KICBnZW9tX2NvbCgpICsNCiAgdGhlbWVfaGMoKSArDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKw0KICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gNykpICsNCiAgbGFicyh4ID0gIiIsIHkgPSAiIiwgdGl0bGUgPSAiUm93cyBwZXIgQ2F0ZWdvcnkiKQ0KDQpwMyA8LSBleHRyYWN0X3RzKGJhcikgJT4lIA0KICBtdXRhdGUobW9udGggPSBtb250aChkYXRlcyksDQogICAgICAgICB5ZWFyID0geWVhcihkYXRlcykpICU+JSANCiAgZ3JvdXBfYnkobW9udGgsIHllYXIsIGlkKSAlPiUgDQogIHN1bW1hcmlzZShzYWxlcyA9IHN1bShzYWxlcyksDQogICAgICAgICAgICBkYXRlcyA9IG1pbihkYXRlcykpICU+JSANCiAgdW5ncm91cCgpICU+JSANCiAgZmlsdGVyKHN0cl9kZXRlY3QoYXMuY2hhcmFjdGVyKGRhdGVzKSwgIi4uLS4uLTAxIikpICU+JSANCiAgZmlsdGVyKGRhdGVzICE9IG1heChkYXRlcykpICU+JSANCiAgbXV0YXRlKHN0YXRlX2lkID0gc3RyX3N1YihpZCwgMSwgMikpICU+JSANCiAgZ2dwbG90KGFlcyhkYXRlcywgc2FsZXMsIGNvbCA9IGlkKSkgKw0KICBnZW9tX2xpbmUoKSArDQogIHRoZW1lX2hjKCkgKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIikgKw0KICBsYWJzKHRpdGxlID0gIlNhbGVzIHBlciBTdG9yZSIsIHggPSAiRGF0ZSIsIHkgPSAiU2FsZXMiLCBjb2wgPSAiU3RvcmUgSUQiKSArDQogIGZhY2V0X3dyYXAofnN0YXRlX2lkKQ0KDQpsYXlvdXQgPC0gIg0KQUFCDQpDQ0MNCiINCg0KcDEgKyBwMiArIHAzICsgcGxvdF9sYXlvdXQoZGVzaWduID0gbGF5b3V0KQ0KYGBgDQoNCmBgYHtyfQ0KbWluX2RhdGUgPC0gZGF0ZSgiMjAxMS0wMS0yOSIpDQoNCmZvbyA8LSB0cmFpbiAlPiUNCiAgZ3JvdXBfYnkoZGVwdF9pZCwgc3RhdGVfaWQpICU+JSANCiAgc3VtbWFyaXNlX2F0KHZhcnMoc3RhcnRzX3dpdGgoImRfIikpLCBzdW0pICU+JSANCiAgdW5ncm91cCgpICU+JSANCiAgc2VsZWN0KGVuZHNfd2l0aCgiaWQiKSwgc3RhcnRzX3dpdGgoImRfIikpICU+JSAgDQogIHBpdm90X2xvbmdlcihzdGFydHNfd2l0aCgiZF8iKSwgbmFtZXNfdG8gPSAiZGF0ZXMiLCB2YWx1ZXNfdG8gPSAic2FsZXMiKSAlPiUNCiAgbXV0YXRlKGRhdGVzID0gYXMuaW50ZWdlcihzdHJfcmVtb3ZlKGRhdGVzLCAiZF8iKSkpICU+JSANCiAgbXV0YXRlKGRhdGVzID0gbWluX2RhdGUgKyBkYXRlcyAtIDEpDQoNCmZvbyAlPiUgDQogIG11dGF0ZShtb250aCA9IG1vbnRoKGRhdGVzKSwNCiAgICAgICAgIHllYXIgPSB5ZWFyKGRhdGVzKSkgJT4lIA0KICBncm91cF9ieShtb250aCwgeWVhciwgZGVwdF9pZCwgc3RhdGVfaWQpICU+JSANCiAgc3VtbWFyaXNlKHNhbGVzID0gc3VtKHNhbGVzKSwNCiAgICAgICAgICAgIGRhdGVzID0gbWluKGRhdGVzKSkgJT4lIA0KICB1bmdyb3VwKCkgJT4lIA0KICBmaWx0ZXIoc3RyX2RldGVjdChhcy5jaGFyYWN0ZXIoZGF0ZXMpLCAiLi4tLi4tMDEiKSkgJT4lIA0KICBmaWx0ZXIoZGF0ZXMgIT0gbWF4KGRhdGVzKSkgJT4lIA0KICBnZ3Bsb3QoYWVzKGRhdGVzLCBzYWxlcywgY29sID0gZGVwdF9pZCkpICsNCiAgZ2VvbV9saW5lKCkgKw0KICBmYWNldF9ncmlkKHN0YXRlX2lkIH4gZGVwdF9pZCkgKw0KICB0aGVtZV90dWZ0ZSgpICsNCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLCBzdHJpcC50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDgpKSArDQogIGxhYnModGl0bGUgPSAiU2FsZXMgcGVyIERlcGFydG1lbnQgYW5kIFN0YXRlIiwgeCA9ICJEYXRlIiwgeSA9ICJTYWxlcyIpDQpgYGANCg0KYGBge3J9DQpmb28gPC0gdHJhaW4gJT4lIA0KICBzdW1tYXJpc2VfYXQodmFycyhzdGFydHNfd2l0aCgiZF8iKSksIHN1bSkgJT4lIA0KICBtdXRhdGUoaWQgPSAxKQ0KDQpiYXIgPC0gZXh0cmFjdF90cyhmb28pICU+JSANCiAgZmlsdGVyKCFzdHJfZGV0ZWN0KGFzLmNoYXJhY3RlcihkYXRlcyksICItMTItMjUiKSkNCg0KbG9lc3NfYWxsIDwtIHByZWRpY3QobG9lc3MoYmFyJHNhbGVzIH4gYXMuaW50ZWdlcihiYXIkZGF0ZXMgLSBtaW4oYmFyJGRhdGVzKSkgKyAxLCBzcGFuID0gMS8yLCBkZWdyZWUgPSAxKSkNCg0KYmFyIDwtIGJhciAlPiUgDQogIG11dGF0ZShsb2VzcyA9IGxvZXNzX2FsbCkgJT4lIA0KICBtdXRhdGUoc2FsZXNfcmVsID0gc2FsZXMgLSBsb2VzcykNCg0KcDEgPC0gYmFyICU+JSANCiAgZ2dwbG90KGFlcyhkYXRlcywgc2FsZXMpKSArDQogIGdlb21fbGluZShjb2wgPSAiYmx1ZSIsIGFscGhhID0gMC41KSArDQogIGdlb21fbGluZShhZXMoZGF0ZXMsIGxvZXNzKSwgY29sID0gImJsYWNrIikgKw0KICB0aGVtZV9oYygpICsNCiAgbGFicyh4ID0gIiIsIHkgPSAiU2FsZXMiLCB0aXRsZSA9ICJUb3RhbCBTYWxlcyB3aXRoIFNtb290aGluZyBGaXQgKyBTZWFzb25hbGl0eSBpbiBSZXNpZHVhbHMiKQ0KDQpwMiA8LSBiYXIgJT4lIA0KICBtdXRhdGUod2RheSA9IHdkYXkoZGF0ZXMsIGxhYmVsID0gVFJVRSwgd2Vla19zdGFydCA9IDEpLA0KICAgICAgICAgbW9udGggPSBtb250aChkYXRlcywgbGFiZWwgPSBUUlVFKSwNCiAgICAgICAgIHllYXIgPSB5ZWFyKGRhdGVzKSkgJT4lIA0KICBncm91cF9ieSh3ZGF5LCBtb250aCwgeWVhcikgJT4lIA0KICBzdW1tYXJpc2Uoc2FsZXMgPSBzdW0oc2FsZXNfcmVsKS8xZTMpICU+JQ0KICBnZ3Bsb3QoYWVzKG1vbnRoLCB3ZGF5LCBmaWxsID0gc2FsZXMpKSArDQogIGdlb21fdGlsZSgpICsNCiAgbGFicyh4ID0gIk1vbnRoIG9mIHRoZSB5ZWFyIiwgeSA9ICJEYXkgb2YgdGhlIHdlZWsiLCBmaWxsID0gIlJlbGF0aXZlIFNhbGVzIFsxa10iKSArDQogIHNjYWxlX2ZpbGxfZGlzdGlsbGVyKHBhbGV0dGUgPSAiU3BlY3RyYWwiKSArDQogIHRoZW1lX2hjKCkNCg0KcDEgLyBwMg0KYGBgDQoNCmBgYHtyfQ0KZm9vIDwtIHRyYWluICU+JQ0KICBncm91cF9ieShzdG9yZV9pZCkgJT4lIA0KICBzdW1tYXJpc2VfYXQodmFycyhzdGFydHNfd2l0aCgiZF8iKSksIHN1bSkgJT4lIA0KICByZW5hbWUoaWQgPSBzdG9yZV9pZCkNCg0KYmFyIDwtIGV4dHJhY3RfdHMoZm9vKSAlPiUgDQogIGZpbHRlcighc3RyX2RldGVjdChhcy5jaGFyYWN0ZXIoZGF0ZXMpLCAiLTEyLTI1IikpICU+JSANCiAgZ3JvdXBfYnkoaWQpICU+JSANCiAgbXV0YXRlKGxvZXNzID0gcHJlZGljdChsb2VzcyhzYWxlcyB+IGFzLmludGVnZXIoZGF0ZXMgLSBtaW4oZGF0ZXMpKSArIDEsIHNwYW4gPSAxLzIsIGRlZ3JlZSA9IDEpKSwNCiAgICAgICAgIG1lYW5fc2FsZXMgPSAoc2FsZXMpKSAlPiUgDQogIG11dGF0ZShzYWxlc19yZWwgPSAoc2FsZXMgLSBsb2VzcykvbWVhbl9zYWxlcykNCg0KcDEgPC0gYmFyICU+JSANCiAgZ2dwbG90KGFlcyhkYXRlcywgc2FsZXMsIGNvbCA9IGlkKSkgKw0KICBnZW9tX2xpbmUoKSArDQogIGdlb21fbGluZShhZXMoZGF0ZXMsIGxvZXNzKSwgY29sID0gImJsYWNrIikgKw0KICBmYWNldF93cmFwKH4gaWQpICsNCiAgdGhlbWVfdHVmdGUoKSArDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKw0KICBsYWJzKHggPSAiIiwgeSA9ICJTYWxlcyIsIHRpdGxlID0gIlNhbGVzIHBlciBTdGF0ZSB3aXRoIFNlYXNvbmFsaXRpZXMiKQ0KDQpgYGANCg0KYGBge3J9DQppZHguQ0EuMT13aGljaChiYXIkaWQgJWluJSAnQ0FfMScpDQppZHguQ0EuMj13aGljaChiYXIkaWQgJWluJSAnQ0FfMicpDQppZHguQ0EuMz13aGljaChiYXIkaWQgJWluJSAnQ0FfMycpDQppZHguQ0EuND13aGljaChiYXIkaWQgJWluJSAnQ0FfNCcpDQoNCmlkeC5XSS4xPXdoaWNoKGJhciRpZCAlaW4lICdXSV8xJykNCmlkeC5XSS4yPXdoaWNoKGJhciRpZCAlaW4lICdXSV8yJykNCmlkeC5XSS4zPXdoaWNoKGJhciRpZCAlaW4lICdXSV8zJykNCg0KaWR4LlRYLjE9d2hpY2goYmFyJGlkICVpbiUgJ1RYXzEnKQ0KaWR4LlRYLjI9d2hpY2goYmFyJGlkICVpbiUgJ1RYXzInKQ0KaWR4LlRYLjM9d2hpY2goYmFyJGlkICVpbiUgJ1RYXzMnKQ0KDQpDYWwuMTwtYmFyJG1lYW5fc2FsZXNbaWR4LkNBLjFdDQpDYWwuMjwtYmFyJG1lYW5fc2FsZXNbaWR4LkNBLjJdDQpDYWwuMzwtYmFyJG1lYW5fc2FsZXNbaWR4LkNBLjNdDQpDYWwuNDwtYmFyJG1lYW5fc2FsZXNbaWR4LkNBLjRdDQpDYWwuMS50czwtdHMoQ2FsLjEsc3RhcnQ9MSxmcmVxPTcpDQpDYWwuMi50czwtdHMoQ2FsLjIsc3RhcnQ9MSxmcmVxPTcpDQpDYWwuMy50czwtdHMoQ2FsLjMsc3RhcnQ9MSxmcmVxPTcpDQpDYWwuNC50czwtdHMoQ2FsLjQsc3RhcnQ9MSxmcmVxPTcpDQpDYWwudG90LnRzPUNhbC4xLnRzK0NhbC4yLnRzK0NhbC4zLnRzK0NhbC40LnRzDQoNCg0KV0kuMTwtYmFyJG1lYW5fc2FsZXNbaWR4LldJLjFdDQpXSS4yPC1iYXIkbWVhbl9zYWxlc1tpZHguV0kuMl0NCldJLjM8LWJhciRtZWFuX3NhbGVzW2lkeC5XSS4zXQ0KV0kuMS50czwtdHMoV0kuMSxzdGFydD0xLGZyZXE9NykNCldJLjIudHM8LXRzKFdJLjIsc3RhcnQ9MSxmcmVxPTcpDQpXSS4zLnRzPC10cyhXSS4zLHN0YXJ0PTEsZnJlcT03KQ0KV0kudG90LnRzPVdJLjEudHMrV0kuMi50cytXSS4zLnRzDQoNCg0KVFguMTwtYmFyJG1lYW5fc2FsZXNbaWR4LlRYLjFdDQpUWC4yPC1iYXIkbWVhbl9zYWxlc1tpZHguVFguMl0NClRYLjM8LWJhciRtZWFuX3NhbGVzW2lkeC5UWC4zXQ0KVFguMS50czwtdHMoVFguMSxzdGFydD0xLGZyZXE9NykNClRYLjIudHM8LXRzKFRYLjIsc3RhcnQ9MSxmcmVxPTcpDQpUWC4zLnRzPC10cyhUWC4zLHN0YXJ0PTEsZnJlcT03KQ0KVFgudG90LnRzPVRYLjEudHMrVFguMi50cytUWC4zLnRzDQoNCldhbC50b3QudHM9Q2FsLnRvdC50cytXSS50b3QudHMrVFgudG90LnRzDQoNCnBhcihtZnJvdz1jKDEsMykpDQpwbG90KENhbC50b3QudHMseGxhYj0iVGltZSAoaW4gd2Vla3MpIikNCnBsb3QoV0kudG90LnRzLHhsYWI9IlRpbWUgKGluIHdlZWtzKSIpDQpwbG90KFRYLnRvdC50cyx4bGFiPSJUaW1lIChpbiB3ZWVrcykiKQ0KDQpyZXF1aXJlKGRsbSkNCg0KIyBDYWx0czwtYmFyJG1lYW5fc2FsZXNbMToxOTA4XQ0KIyBXSXRzPC1iYXIkbWVhbl9zYWxlc1sxOTA5OjM4MTZdDQojIFRYdHM8LWJhciRtZWFuX3NhbGVzWzM4MTc6NTcyNF0NCiMgDQojIENBLnRzIDwtIHRzKENhbHRzLHN0YXJ0PTEsZnJlcT03KQ0KIyBXSS50cyA8LSB0cyhXSXRzLHN0YXJ0PTEsZnJlcT03KQ0KIyBUWC50cyA8LSB0cyhUWHRzLHN0YXJ0PTEsZnJlcT03KQ0KYGBgDQoNCg0KDQojIGBgYHtyfQ0KIyBsaWJyYXJ5KGRwbHlyKQ0KIyB3YWwgPC1yZWFkLmNzdihmaWxlPSdzYWxlc190cmFpbl92YWxpZGF0aW9uLmNzdicpDQojIGR0PC1hcHBseSh3YWwsIDEsIGZ1bmN0aW9uKHIpIGFueShyICVpbiUgYygiQ0EiKSkpDQojIENhbGRhdGFjaGs8LWFzLm1hdHJpeCh3YWxbZHQsNzoxOTE5XSkNCiMgQ2FsdHM8LSBjb2xTdW1zKENhbGRhdGFjaGspDQojIGRpbShDYWx0cykNCiMgQ2FsLnRzIDwtIHRzKENhbHRzLHN0YXJ0PTEsZnJlcT03KQ0KIyBgYGANCiMgDQojIA0KIyBgYGB7cn0NCiMgZHQyPC1hcHBseSh3YWwsIDEsIGZ1bmN0aW9uKHIpIGFueShyICVpbiUgYygiVFgiKSkpDQojIHN2PC1hcy5tYXRyaXgod2FsW2R0Miw3OjE5MTldKQ0KIyBUWGRhdGE8LSBjb2xTdW1zKHN2KQ0KIyBUWC50cyA8LSB0cyhUWGRhdGEsc3RhcnQ9MSxmcmVxPTcpDQojIA0KIyBgYGANCiMgDQojIA0KIyBgYGB7cn0NCiMgZHQzPC1hcHBseSh3YWwsIDEsIGZ1bmN0aW9uKHIpIGFueShyICVpbiUgYygiV0kiKSkpDQojIFdJZGF0YTwtIGNvbFN1bXMoYXMubWF0cml4KHdhbFtkdDMsNzoxOTE5XSkpDQojIFdJLnRzIDwtIHRzKFdJZGF0YSxzdGFydD0xLGZyZXE9NykNCiMgcGxvdChXSS50cyx4bGFiPSJUaW1lIChpbiBkYXlzKSIpDQoNCg0KDQpUaGUgdGhyZWUgdGltZSBzZXJpZXMgZm9yIGVhY2ggb2YgdGhlIHN0YXRlcyBhcmUgcmVwcmVzZW50ZWQgYXMgYWJvdmUsIGl0IGNsZWFybHkgc2hvd3Mgc2Vhc29uYWxpdHksIHdpdGggdGhlIGNocmlzdG1hcyBkYXkgaGF2ZSB6ZXJvIHNhbGVzLiBXZSBuZWVkIHRvIHByb3ZpZGUgc3VjaCBleHRyYSBiaXQgb2YgaW5mb3JtYXRpb24oYnV0IGhvdz8pDQoNClRoZSBjb21iaW5lZCB0aW1lIHNlcmllcyBzaG93cyBoZWF2eSBzZWFzb25hbGl0eSBhcyB3ZWxsLiANCmBgYHtyfQ0KDQoNCmxvZy5DQS50cz1sb2coKFdhbC50b3QudHMpKQ0KcGxvdChsb2cuQ0EudHMpDQoNCmxvZy5XSS50cz1zcXJ0KFdJLnRvdC50cykNCnBsb3QobG9nLldJLnRzKQ0KDQpsb2cuVFgudHM9c3FydChUWC50b3QudHMpDQpwbG90KGxvZy5UWC50cykNCg0KDQpgYGANCihBS1NIQVQpLCBsb29rIHRoaXMgY2h1bmsgb2YgY29kZS4gDQpgYGB7cn0NCiMgRExNIHdpdGggcG9seW5vbWlhbCBzZWNvbmQtb3JkZXIgdHJlbmQgYW5kIHNlYXNvbmFsaXR5IG1vZGVsZWQgd2l0aCBhIHNlYXNvbmFsIGZhY3RvciByZXByZXNlbnRhdGlvbi4NCmJ1aWxkIDwtIGZ1bmN0aW9uKHBhcm0pIHsNCiAgZGxtTW9kUG9seShvcmRlciA9IDIsIGRWID0gZXhwKHBhcm1bMV0pLCBkVyA9IGMoZXhwKHBhcm1bMl0pLGV4cChwYXJtWzNdKSkpICsgZGxtTW9kVHJpZyhzID0gNywgZFYgPSAwLCBkVz1leHAocGFybVs0XSkpK2RsbU1vZFRyaWcocyA9IDMwLHE9NSwgZFYgPSAwLCBkVz1leHAocGFybVs1XSkpK2RsbU1vZFRyaWcocyA9IDM2NSxxPTEsIGRWID0gMCwgZFc9ZXhwKHBhcm1bNl0pKQ0KfQ0KZml0IDwtIGRsbU1MRShsb2cuQ0EudHMsIHJlcCgwLDYpLCBidWlsZCkNCmZpdCRjb252ZXJnZW5jZQ0KDQpCSUMuMm5kLnNlYXNmYWN0b3IgPC0gIDIgKiAgZml0JHZhbHVlICsgbGVuZ3RoKGZpdCRwYXIpICogbG9nKGxlbmd0aChsb2cuQ0EudHMpKQ0KcHJpbnQoIkJJQyIpDQpCSUMuMm5kLnNlYXNmYWN0b3INCg0KbW9kZWwyIDwtIGJ1aWxkKGZpdCRwYXIpICAjVGhpcyBpcyBwYXJ0IHdoZXJlIGhlIHRha2VzIHRoZSBtb2RlbCBwYXJhbWV0ZXJzDQpwcmludCgiT2JzZXJ2YXRpb25hbCBub2lzZSBmcm9tIE1MRSIpDQptb2RlbDIkVg0KcHJpbnQoIklubm92YXRpb24gdmFyaWFuY2UgbWF0cml4IGRpYWdvbmFsIGVsZW1lbnRzIGZyb20gTUxFIikNCm1vZGVsMiRXWzE6MiwxOjJdDQoNCmxvZy5DQS5maWx0MiA8LSBkbG1GaWx0ZXIobG9nLkNBLnRzLCBtb2RlbDIpDQoNCmNvdi5maWx0IDwtIHdpdGgobG9nLkNBLmZpbHQyLCBkbG1TdmQydmFyKFUuQywgRC5DKSkNCg0Kc2Vhcy50ZXJtID0gMg0KDQpzZC5zZWFzb25hbGl0eS5maWx0MiA8LSByZXAoTkEsbGVuZ3RoKGNvdi5maWx0KSkNCmZvcihpIGluIDE6bGVuZ3RoKGNvdi5maWx0KSkgc2Quc2Vhc29uYWxpdHkuZmlsdDJbaV0gPSBzcXJ0KGNvdi5maWx0W1tpXV1bc2Vhcy50ZXJtLHNlYXMudGVybV0pDQpzZC5zZWFzb25hbGl0eS5maWx0MiA9IHRzKHNkLnNlYXNvbmFsaXR5LmZpbHQyWy0oMTo4KV0sZnJlcXVlbmN5PTcpDQpzZWFzb25hbGl0eS5maWx0MiA9IHRzKGxvZy5DQS5maWx0MiRtWy0oMTo4KSxzZWFzLnRlcm1dLGZyZXF1ZW5jeT03KQ0KbGwgPSBzZWFzb25hbGl0eS5maWx0MiAtIDEuOTYgKiBzZC5zZWFzb25hbGl0eS5maWx0Mg0KdWwgPSBzZWFzb25hbGl0eS5maWx0MiArIDEuOTYgKiBzZC5zZWFzb25hbGl0eS5maWx0Mg0KbGxpbSA9IG1pbihsbCkNCnVsaW0gPSBtYXgodWwpDQpwbG90KHNlYXNvbmFsaXR5LmZpbHQyLHlsaW09YyhsbGltLHVsaW0pKQ0KbGluZXMobGwsbHR5PTIsY29sPSJncmVlbiIpDQpsaW5lcyh1bCxsdHk9Mixjb2w9ImdyZWVuIikNCmxsaW0gPSBtaW4oYyhtaW4oc2Vhc29uYWxpdHkuZmlsdDIvc2Quc2Vhc29uYWxpdHkuZmlsdDIpLC0xLjk2KSkNCnVsaW0gPSBtYXgoYyhtYXgoc2Vhc29uYWxpdHkuZmlsdDIvc2Quc2Vhc29uYWxpdHkuZmlsdDIpLDEuOTYpKQ0KcGxvdChzZWFzb25hbGl0eS5maWx0Mi9zZC5zZWFzb25hbGl0eS5maWx0Mix5bGltPWMobGxpbSx1bGltKSkNCmFibGluZShoPTEuOTYsbHR5PTIpDQphYmxpbmUoaD0tMS45NixsdHk9MikNCg0Kc2Vhcy50ZXJtID0gNA0KDQpzZC5zZWFzb25hbGl0eS5maWx0MiA8LSByZXAoTkEsbGVuZ3RoKGNvdi5maWx0KSkNCmZvcihpIGluIDE6bGVuZ3RoKGNvdi5maWx0KSkgc2Quc2Vhc29uYWxpdHkuZmlsdDJbaV0gPSBzcXJ0KGNvdi5maWx0W1tpXV1bc2Vhcy50ZXJtLHNlYXMudGVybV0pDQpzZC5zZWFzb25hbGl0eS5maWx0MiA9IHRzKHNkLnNlYXNvbmFsaXR5LmZpbHQyWy0oMTo4KV0sZnJlcXVlbmN5PTcpDQpzZWFzb25hbGl0eS5maWx0MiA9IHRzKGxvZy5DQS5maWx0MiRtWy0oMTo4KSxzZWFzLnRlcm1dLGZyZXF1ZW5jeT03KQ0KbGwgPSBzZWFzb25hbGl0eS5maWx0MiAtIDEuOTYgKiBzZC5zZWFzb25hbGl0eS5maWx0Mg0KdWwgPSBzZWFzb25hbGl0eS5maWx0MiArIDEuOTYgKiBzZC5zZWFzb25hbGl0eS5maWx0Mg0KbGxpbSA9IG1pbihsbCkNCnVsaW0gPSBtYXgodWwpDQpwbG90KHNlYXNvbmFsaXR5LmZpbHQyLHlsaW09YyhsbGltLHVsaW0pKQ0KbGluZXMobGwsbHR5PTIsY29sPSJncmVlbiIpDQpsaW5lcyh1bCxsdHk9Mixjb2w9ImdyZWVuIikNCmxsaW0gPSBtaW4oYyhtaW4oc2Vhc29uYWxpdHkuZmlsdDIvc2Quc2Vhc29uYWxpdHkuZmlsdDIpLC0xLjk2KSkNCnVsaW0gPSBtYXgoYyhtYXgoc2Vhc29uYWxpdHkuZmlsdDIvc2Quc2Vhc29uYWxpdHkuZmlsdDIpLDEuOTYpKQ0KcGxvdChzZWFzb25hbGl0eS5maWx0Mi9zZC5zZWFzb25hbGl0eS5maWx0Mix5bGltPWMobGxpbSx1bGltKSkNCmFibGluZShoPTEuOTYsbHR5PTIpDQphYmxpbmUoaD0tMS45NixsdHk9MikNCg0KDQoNCnNlYXMudGVybSA9IDYNCg0Kc2Quc2Vhc29uYWxpdHkuZmlsdDIgPC0gcmVwKE5BLGxlbmd0aChjb3YuZmlsdCkpDQpmb3IoaSBpbiAxOmxlbmd0aChjb3YuZmlsdCkpIHNkLnNlYXNvbmFsaXR5LmZpbHQyW2ldID0gc3FydChjb3YuZmlsdFtbaV1dW3NlYXMudGVybSxzZWFzLnRlcm1dKQ0Kc2Quc2Vhc29uYWxpdHkuZmlsdDIgPSB0cyhzZC5zZWFzb25hbGl0eS5maWx0MlstKDE6OCldLGZyZXF1ZW5jeT03KQ0Kc2Vhc29uYWxpdHkuZmlsdDIgPSB0cyhsb2cuQ0EuZmlsdDIkbVstKDE6OCksc2Vhcy50ZXJtXSxmcmVxdWVuY3k9NykNCmxsID0gc2Vhc29uYWxpdHkuZmlsdDIgLSAxLjk2ICogc2Quc2Vhc29uYWxpdHkuZmlsdDINCnVsID0gc2Vhc29uYWxpdHkuZmlsdDIgKyAxLjk2ICogc2Quc2Vhc29uYWxpdHkuZmlsdDINCmxsaW0gPSBtaW4obGwpDQp1bGltID0gbWF4KHVsKQ0KcGxvdChzZWFzb25hbGl0eS5maWx0Mix5bGltPWMobGxpbSx1bGltKSkNCmxpbmVzKGxsLGx0eT0yLGNvbD0iZ3JlZW4iKQ0KbGluZXModWwsbHR5PTIsY29sPSJncmVlbiIpDQpsbGltID0gbWluKGMobWluKHNlYXNvbmFsaXR5LmZpbHQyL3NkLnNlYXNvbmFsaXR5LmZpbHQyKSwtMS45NikpDQp1bGltID0gbWF4KGMobWF4KHNlYXNvbmFsaXR5LmZpbHQyL3NkLnNlYXNvbmFsaXR5LmZpbHQyKSwxLjk2KSkNCnBsb3Qoc2Vhc29uYWxpdHkuZmlsdDIvc2Quc2Vhc29uYWxpdHkuZmlsdDIseWxpbT1jKGxsaW0sdWxpbSkpDQphYmxpbmUoaD0xLjk2LGx0eT0yKQ0KYWJsaW5lKGg9LTEuOTYsbHR5PTIpDQoNCg0Kc2Vhcy50ZXJtID0gOA0KDQpzZC5zZWFzb25hbGl0eS5maWx0MiA8LSByZXAoTkEsbGVuZ3RoKGNvdi5maWx0KSkNCmZvcihpIGluIDE6bGVuZ3RoKGNvdi5maWx0KSkgc2Quc2Vhc29uYWxpdHkuZmlsdDJbaV0gPSBzcXJ0KGNvdi5maWx0W1tpXV1bc2Vhcy50ZXJtLHNlYXMudGVybV0pDQpzZC5zZWFzb25hbGl0eS5maWx0MiA9IHRzKHNkLnNlYXNvbmFsaXR5LmZpbHQyWy0oMTo4KV0sZnJlcXVlbmN5PTcpDQpzZWFzb25hbGl0eS5maWx0MiA9IHRzKGxvZy5DQS5maWx0MiRtWy0oMTo4KSxzZWFzLnRlcm1dLGZyZXF1ZW5jeT03KQ0KbGwgPSBzZWFzb25hbGl0eS5maWx0MiAtIDEuOTYgKiBzZC5zZWFzb25hbGl0eS5maWx0Mg0KdWwgPSBzZWFzb25hbGl0eS5maWx0MiArIDEuOTYgKiBzZC5zZWFzb25hbGl0eS5maWx0Mg0KbGxpbSA9IG1pbihsbCkNCnVsaW0gPSBtYXgodWwpDQpwbG90KHNlYXNvbmFsaXR5LmZpbHQyLHlsaW09YyhsbGltLHVsaW0pKQ0KbGluZXMobGwsbHR5PTIsY29sPSJncmVlbiIpDQpsaW5lcyh1bCxsdHk9Mixjb2w9ImdyZWVuIikNCmxsaW0gPSBtaW4oYyhtaW4oc2Vhc29uYWxpdHkuZmlsdDIvc2Quc2Vhc29uYWxpdHkuZmlsdDIpLC0xLjk2KSkNCnVsaW0gPSBtYXgoYyhtYXgoc2Vhc29uYWxpdHkuZmlsdDIvc2Quc2Vhc29uYWxpdHkuZmlsdDIpLDEuOTYpKQ0KcGxvdChzZWFzb25hbGl0eS5maWx0Mi9zZC5zZWFzb25hbGl0eS5maWx0Mix5bGltPWMobGxpbSx1bGltKSkNCmFibGluZShoPTEuOTYsbHR5PTIpDQphYmxpbmUoaD0tMS45NixsdHk9MikNCg0KDQoNCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjDQojICAgRm9yZWNhc3RpbmcgICAjDQojIyMjIyMjIyMjIyMjIyMjIyMjDQoNCnByZWRpY3Rpb25zIDwtIGRsbUZvcmVjYXN0KGxvZy5DQS5maWx0Miwgbj0yOCkNCg0KbGwgPSBwcmVkaWN0aW9ucyRmIC0gMS45NiAqIHNxcnQodW5saXN0KHByZWRpY3Rpb25zJFEpKQ0KdWwgPSBwcmVkaWN0aW9ucyRmICsgMS45NiAqIHNxcnQodW5saXN0KHByZWRpY3Rpb25zJFEpKQ0KcGxvdChsb2cuQ0EudHMsIHhsYWIgPSAiIiwgY29sID0gImRhcmtncmV5Iix4bGltPWMoMjUwLDMwMCksbHdkPTIpDQojcGxvdChsb2cuY2hvYywgeGxhYiA9ICIiLCBjb2wgPSAiZGFya2dyZXkiLHhsaW09YygxOTU4LDIwMDApLCB5bGltPWMoMTAwMCwxMDAwMCksbHdkPTIpDQpsaW5lcyhwcmVkaWN0aW9ucyRmLCBjb2w9InJlZCIsbHdkPTIpDQpsaW5lcyhsbCxsdHk9MiwgY29sPSJncmVlbiIsbHdkPTIpDQpsaW5lcyh1bCxsdHk9MiwgY29sPSJncmVlbiIsbHdkPTIpDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyAgICAgICAgICBPbmUtc3RlcCBhaGVhZCBmb3JlY2FzdCBlcnJvciBmb3IgdGhlIGxhc3QgOSB5ZWFycyAgICAgICAgICAgICAgICAjDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCnByaW50KCIgTWVhbiBhYnNvbHV0ZSBmb3JlY2FzdCBlcnJvciIpDQojIE1lYW4gYWJzb2x1dGUgZm9yZWNhc3QgZXJyb3IgKE1BRSkNCm1lYW4oYWJzKGxvZy5DQS5maWx0MiRmWzE4MDA6MTkwOF0gLSBsb2cuQ0EudHNbMTgwMDoxOTA4XSkpDQoNCnByaW50KCIgTWVhbiBzcXVhcmVkIGZvcmVjYXN0IGVycm9yIChNU0UpIikNCiMgTWVhbiBzcXVhcmVkIGZvcmVjYXN0IGVycm9yIChNU0UpDQptZWFuKChsb2cuQ0EuZmlsdDIkZlsxODAwOjE5MDhdIC0gbG9nLkNBLnRzWzE4MDA6MTkwOF0pXjIpDQoNCnByaW50KCIgTWVhbiBhYnNvbHV0ZSBwZXJjZW50YWdlIGZvcmVjYXN0IGVycm9yIChNQVBFKSIpDQojIE1lYW4gYWJzb2x1dGUgcGVyY2VudGFnZSBmb3JlY2FzdCBlcnJvciAoTUFQRSkNCm1lYW4oYWJzKGxvZy5DQS5maWx0MiRmWzE4MDA6MTkwOF0gLSBsb2cuQ0EudHNbMTgwMDoxOTA4XSkgLyBsb2cuQ0EudHNbMTgwMDoxOTA4XSkNCg0KcGxvdChsb2cuQ0EuZmlsdDIkZix5bGltPWMoOCwxMikpDQpsaW5lcyhsb2cuQ0EudHMsY29sPSJncmVlbiIpDQoNCmBgYA0KYGBge3J9DQojIEZvbGxvd2luZyBzbmlwcGV0IG9mIGNjb2RlIGlzIGZvciBtb2RlbCBkaWFnb25zdGljcw0KIyBHZXQgb25lLXN0ZXAgYWhlYWQgZm9yZWNhc3QgZXJyb3JzDQpyZXMgPC0gcmVzaWR1YWxzKGxvZy5DQS5maWx0Miwgc2Q9RkFMU0UpDQoNCiMgUGxvdCBvbmUtc3RlcCBhaGVhZCBmb3JlY2FzdCBlcnJvcnMNCg0KcGxvdChyZXMsdHlwZT0naCcpOyBhYmxpbmUoaD0wKQ0KcGFyKG1mcm93PWMoMSwyKSkNCmFjZihyZXMsbGFnLm1heCA9IDIwMCkNCnBhY2YocmVzLGxhZy5tYXggPSAyMDApDQoNCiMgUGxvdCBxcS1wbG90IG9mIG9uZS1zdGVwIGFoZWFkIGZvcmVjYXN0IGVycm9ycw0KcXFub3JtKHJlcyk7IHFxbGluZShyZXMpDQoNCg0KIyBUZXN0IG5vcm1hbGl0eSB3aXRoIHRoZSBTaGFwaXJvLVdpbGsgbm9ybWFsaXR5IHRlc3QNCiMgSF8wOiBlcnJvcnMgYXJlIG5vcm1hbGx5IGRpc3RyaWJ1dGlvbg0KIyBIX0E6IGVycm9ycyBhcmUgbm90IG5vcm1hbGx5IGRpc3RyaWJ1dGlvbg0Kc2hhcGlyby50ZXN0KHJlcykNCg0KDQojIFRlc3QgYXV0b2NvcnJlbGF0aW9uIHdpdGggdGhlIExqdW5nLUJveCB0ZXN0DQojIEhfMDogZXJyb3JzIGFyZSBpbmRlcGVuZGVudA0KIyBIX0E6IGVycm9ycyBleGhpYml0IHNlcmlhbCBjb3JyZWxhdGlvbg0KIEJveC50ZXN0KHJlcywgbGFnPTIwLCB0eXBlPSJManVuZyIpICAgDQpzYXBwbHkoMSA6IDIwLCBmdW5jdGlvbihpKQ0KICAgICAgIEJveC50ZXN0KHJlcywgbGFnID0gaSwgdHlwZSA9ICJManVuZy1Cb3giKSRwLnZhbHVlKQ0KYGBgDQoNCg0KYGBge3J9DQojIERMTSB3aXRoIHBvbHlub21pYWwgc2Vjb25kLW9yZGVyIHRyZW5kIGFuZCBzZWFzb25hbGl0eSBtb2RlbGVkIHdpdGggYSBzZWFzb25hbCBmYWN0b3IgcmVwcmVzZW50YXRpb24uDQpidWlsZCA8LSBmdW5jdGlvbihwYXJtKSB7DQogIGRsbU1vZFBvbHkob3JkZXIgPSAyLCBkViA9IGV4cChwYXJtWzFdKSwgZFcgPSBjKGV4cChwYXJtWzJdKSxleHAocGFybVszXSkpKSArIGRsbU1vZFRyaWcocyA9IDcsIGRWID0gMCwgZFc9ZXhwKHBhcm1bNF0pKQ0KfQ0KZml0IDwtIGRsbU1MRShsb2cuV0kudHMsIHJlcCgwLDQpLCBidWlsZCkNCmZpdCRjb252ZXJnZW5jZQ0KDQpCSUMuMm5kLnNlYXNmYWN0b3IgPC0gIDIgKiAgZml0JHZhbHVlICsgbGVuZ3RoKGZpdCRwYXIpICogbG9nKGxlbmd0aChsb2cuV0kudHMpKQ0KcHJpbnQoIkJJQyIpDQpCSUMuMm5kLnNlYXNmYWN0b3INCg0KbW9kZWwuV0kgPC0gYnVpbGQoZml0JHBhcikgICNUaGlzIGlzIHBhcnQgd2hlcmUgaGUgdGFrZXMgdGhlIG1vZGVsIHBhcmFtZXRlcnMNCnByaW50KCJPYnNlcnZhdGlvbmFsIG5vaXNlIGZyb20gTUxFIikNCm1vZGVsLldJJFYNCnByaW50KCJJbm5vdmF0aW9uIHZhcmlhbmNlIG1hdHJpeCBkaWFnb25hbCBlbGVtZW50cyBmcm9tIE1MRSIpDQptb2RlbC5XSSRXWzE6MiwxOjJdDQoNCmxvZy5XSS5maWx0MiA8LSBkbG1GaWx0ZXIobG9nLldJLnRzLCBtb2RlbC5XSSkNCg0KY292LmZpbHQgPC0gd2l0aChsb2cuV0kuZmlsdDIsIGRsbVN2ZDJ2YXIoVS5DLCBELkMpKQ0KDQpzZWFzLnRlcm0gPSAyDQoNCnNkLnNlYXNvbmFsaXR5LmZpbHQyIDwtIHJlcChOQSxsZW5ndGgoY292LmZpbHQpKQ0KZm9yKGkgaW4gMTpsZW5ndGgoY292LmZpbHQpKSBzZC5zZWFzb25hbGl0eS5maWx0MltpXSA9IHNxcnQoY292LmZpbHRbW2ldXVtzZWFzLnRlcm0sc2Vhcy50ZXJtXSkNCnNkLnNlYXNvbmFsaXR5LmZpbHQyID0gdHMoc2Quc2Vhc29uYWxpdHkuZmlsdDJbLSgxOjgpXSxmcmVxdWVuY3k9NykNCnNlYXNvbmFsaXR5LmZpbHQyID0gdHMobG9nLldJLmZpbHQyJG1bLSgxOjgpLHNlYXMudGVybV0sZnJlcXVlbmN5PTcpDQpsbCA9IHNlYXNvbmFsaXR5LmZpbHQyIC0gMS45NiAqIHNkLnNlYXNvbmFsaXR5LmZpbHQyDQp1bCA9IHNlYXNvbmFsaXR5LmZpbHQyICsgMS45NiAqIHNkLnNlYXNvbmFsaXR5LmZpbHQyDQpsbGltID0gbWluKGxsKQ0KdWxpbSA9IG1heCh1bCkNCnBsb3Qoc2Vhc29uYWxpdHkuZmlsdDIseWxpbT1jKGxsaW0sdWxpbSkpDQpsaW5lcyhsbCxsdHk9Mixjb2w9ImdyZWVuIikNCmxpbmVzKHVsLGx0eT0yLGNvbD0iZ3JlZW4iKQ0KbGxpbSA9IG1pbihjKG1pbihzZWFzb25hbGl0eS5maWx0Mi9zZC5zZWFzb25hbGl0eS5maWx0MiksLTEuOTYpKQ0KdWxpbSA9IG1heChjKG1heChzZWFzb25hbGl0eS5maWx0Mi9zZC5zZWFzb25hbGl0eS5maWx0MiksMS45NikpDQpwbG90KHNlYXNvbmFsaXR5LmZpbHQyL3NkLnNlYXNvbmFsaXR5LmZpbHQyLHlsaW09YyhsbGltLHVsaW0pKQ0KYWJsaW5lKGg9MS45NixsdHk9MikNCmFibGluZShoPS0xLjk2LGx0eT0yKQ0KDQpzZWFzLnRlcm0gPSA0DQoNCnNkLnNlYXNvbmFsaXR5LmZpbHQyIDwtIHJlcChOQSxsZW5ndGgoY292LmZpbHQpKQ0KZm9yKGkgaW4gMTpsZW5ndGgoY292LmZpbHQpKSBzZC5zZWFzb25hbGl0eS5maWx0MltpXSA9IHNxcnQoY292LmZpbHRbW2ldXVtzZWFzLnRlcm0sc2Vhcy50ZXJtXSkNCnNkLnNlYXNvbmFsaXR5LmZpbHQyID0gdHMoc2Quc2Vhc29uYWxpdHkuZmlsdDJbLSgxOjgpXSxmcmVxdWVuY3k9NykNCnNlYXNvbmFsaXR5LmZpbHQyID0gdHMobG9nLldJLmZpbHQyJG1bLSgxOjgpLHNlYXMudGVybV0sZnJlcXVlbmN5PTcpDQpsbCA9IHNlYXNvbmFsaXR5LmZpbHQyIC0gMS45NiAqIHNkLnNlYXNvbmFsaXR5LmZpbHQyDQp1bCA9IHNlYXNvbmFsaXR5LmZpbHQyICsgMS45NiAqIHNkLnNlYXNvbmFsaXR5LmZpbHQyDQpsbGltID0gbWluKGxsKQ0KdWxpbSA9IG1heCh1bCkNCnBsb3Qoc2Vhc29uYWxpdHkuZmlsdDIseWxpbT1jKGxsaW0sdWxpbSkpDQpsaW5lcyhsbCxsdHk9Mixjb2w9ImdyZWVuIikNCmxpbmVzKHVsLGx0eT0yLGNvbD0iZ3JlZW4iKQ0KbGxpbSA9IG1pbihjKG1pbihzZWFzb25hbGl0eS5maWx0Mi9zZC5zZWFzb25hbGl0eS5maWx0MiksLTEuOTYpKQ0KdWxpbSA9IG1heChjKG1heChzZWFzb25hbGl0eS5maWx0Mi9zZC5zZWFzb25hbGl0eS5maWx0MiksMS45NikpDQpwbG90KHNlYXNvbmFsaXR5LmZpbHQyL3NkLnNlYXNvbmFsaXR5LmZpbHQyLHlsaW09YyhsbGltLHVsaW0pKQ0KYWJsaW5lKGg9MS45NixsdHk9MikNCmFibGluZShoPS0xLjk2LGx0eT0yKQ0KDQoNCg0Kc2Vhcy50ZXJtID0gNg0KDQpzZC5zZWFzb25hbGl0eS5maWx0MiA8LSByZXAoTkEsbGVuZ3RoKGNvdi5maWx0KSkNCmZvcihpIGluIDE6bGVuZ3RoKGNvdi5maWx0KSkgc2Quc2Vhc29uYWxpdHkuZmlsdDJbaV0gPSBzcXJ0KGNvdi5maWx0W1tpXV1bc2Vhcy50ZXJtLHNlYXMudGVybV0pDQpzZC5zZWFzb25hbGl0eS5maWx0MiA9IHRzKHNkLnNlYXNvbmFsaXR5LmZpbHQyWy0oMTo4KV0sZnJlcXVlbmN5PTcpDQpzZWFzb25hbGl0eS5maWx0MiA9IHRzKGxvZy5XSS5maWx0MiRtWy0oMTo4KSxzZWFzLnRlcm1dLGZyZXF1ZW5jeT03KQ0KbGwgPSBzZWFzb25hbGl0eS5maWx0MiAtIDEuOTYgKiBzZC5zZWFzb25hbGl0eS5maWx0Mg0KdWwgPSBzZWFzb25hbGl0eS5maWx0MiArIDEuOTYgKiBzZC5zZWFzb25hbGl0eS5maWx0Mg0KbGxpbSA9IG1pbihsbCkNCnVsaW0gPSBtYXgodWwpDQpwbG90KHNlYXNvbmFsaXR5LmZpbHQyLHlsaW09YyhsbGltLHVsaW0pKQ0KbGluZXMobGwsbHR5PTIsY29sPSJncmVlbiIpDQpsaW5lcyh1bCxsdHk9Mixjb2w9ImdyZWVuIikNCmxsaW0gPSBtaW4oYyhtaW4oc2Vhc29uYWxpdHkuZmlsdDIvc2Quc2Vhc29uYWxpdHkuZmlsdDIpLC0xLjk2KSkNCnVsaW0gPSBtYXgoYyhtYXgoc2Vhc29uYWxpdHkuZmlsdDIvc2Quc2Vhc29uYWxpdHkuZmlsdDIpLDEuOTYpKQ0KcGxvdChzZWFzb25hbGl0eS5maWx0Mi9zZC5zZWFzb25hbGl0eS5maWx0Mix5bGltPWMobGxpbSx1bGltKSkNCmFibGluZShoPTEuOTYsbHR5PTIpDQphYmxpbmUoaD0tMS45NixsdHk9MikNCg0KDQpzZWFzLnRlcm0gPSA4DQoNCnNkLnNlYXNvbmFsaXR5LmZpbHQyIDwtIHJlcChOQSxsZW5ndGgoY292LmZpbHQpKQ0KZm9yKGkgaW4gMTpsZW5ndGgoY292LmZpbHQpKSBzZC5zZWFzb25hbGl0eS5maWx0MltpXSA9IHNxcnQoY292LmZpbHRbW2ldXVtzZWFzLnRlcm0sc2Vhcy50ZXJtXSkNCnNkLnNlYXNvbmFsaXR5LmZpbHQyID0gdHMoc2Quc2Vhc29uYWxpdHkuZmlsdDJbLSgxOjgpXSxmcmVxdWVuY3k9NykNCnNlYXNvbmFsaXR5LmZpbHQyID0gdHMobG9nLldJLmZpbHQyJG1bLSgxOjgpLHNlYXMudGVybV0sZnJlcXVlbmN5PTcpDQpsbCA9IHNlYXNvbmFsaXR5LmZpbHQyIC0gMS45NiAqIHNkLnNlYXNvbmFsaXR5LmZpbHQyDQp1bCA9IHNlYXNvbmFsaXR5LmZpbHQyICsgMS45NiAqIHNkLnNlYXNvbmFsaXR5LmZpbHQyDQpsbGltID0gbWluKGxsKQ0KdWxpbSA9IG1heCh1bCkNCnBsb3Qoc2Vhc29uYWxpdHkuZmlsdDIseWxpbT1jKGxsaW0sdWxpbSkpDQpsaW5lcyhsbCxsdHk9Mixjb2w9ImdyZWVuIikNCmxpbmVzKHVsLGx0eT0yLGNvbD0iZ3JlZW4iKQ0KbGxpbSA9IG1pbihjKG1pbihzZWFzb25hbGl0eS5maWx0Mi9zZC5zZWFzb25hbGl0eS5maWx0MiksLTEuOTYpKQ0KdWxpbSA9IG1heChjKG1heChzZWFzb25hbGl0eS5maWx0Mi9zZC5zZWFzb25hbGl0eS5maWx0MiksMS45NikpDQpwbG90KHNlYXNvbmFsaXR5LmZpbHQyL3NkLnNlYXNvbmFsaXR5LmZpbHQyLHlsaW09YyhsbGltLHVsaW0pKQ0KYWJsaW5lKGg9MS45NixsdHk9MikNCmFibGluZShoPS0xLjk2LGx0eT0yKQ0KDQoNCg0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgICBGb3JlY2FzdGluZyAgICMNCiMjIyMjIyMjIyMjIyMjIyMjIyMNCg0KcHJlZGljdGlvbnMgPC0gZGxtRm9yZWNhc3QobG9nLldJLmZpbHQyLCBuPTI4KQ0KDQpsbCA9IHByZWRpY3Rpb25zJGYgLSAxLjk2ICogc3FydCh1bmxpc3QocHJlZGljdGlvbnMkUSkpDQp1bCA9IHByZWRpY3Rpb25zJGYgKyAxLjk2ICogc3FydCh1bmxpc3QocHJlZGljdGlvbnMkUSkpDQpwbG90KGxvZy5XSS50cywgeGxhYiA9ICIiLCBjb2wgPSAiZGFya2dyZXkiLHhsaW09YygyNTAsMzAwKSxsd2Q9MikNCiNwbG90KGxvZy5jaG9jLCB4bGFiID0gIiIsIGNvbCA9ICJkYXJrZ3JleSIseGxpbT1jKDE5NTgsMjAwMCksIHlsaW09YygxMDAwLDEwMDAwKSxsd2Q9MikNCmxpbmVzKHByZWRpY3Rpb25zJGYsIGNvbD0icmVkIixsd2Q9MikNCmxpbmVzKGxsLGx0eT0yLCBjb2w9ImdyZWVuIixsd2Q9MikNCmxpbmVzKHVsLGx0eT0yLCBjb2w9ImdyZWVuIixsd2Q9MikNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojICAgICAgICAgIE9uZS1zdGVwIGFoZWFkIGZvcmVjYXN0IGVycm9yIGZvciB0aGUgbGFzdCA5IHllYXJzICAgICAgICAgICAgICAgICMNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KcHJpbnQoIiBNZWFuIGFic29sdXRlIGZvcmVjYXN0IGVycm9yIikNCiMgTWVhbiBhYnNvbHV0ZSBmb3JlY2FzdCBlcnJvciAoTUFFKQ0KbWVhbihhYnMobG9nLldJLmZpbHQyJGZbMTgwMDoxOTA4XSAtIGxvZy5XSS50c1sxODAwOjE5MDhdKSkNCg0KcHJpbnQoIiBNZWFuIHNxdWFyZWQgZm9yZWNhc3QgZXJyb3IgKE1TRSkiKQ0KIyBNZWFuIHNxdWFyZWQgZm9yZWNhc3QgZXJyb3IgKE1TRSkNCm1lYW4oKGxvZy5XSS5maWx0MiRmWzE4MDA6MTkwOF0gLSBsb2cuV0kudHNbMTgwMDoxOTA4XSleMikNCg0KcHJpbnQoIiBNZWFuIGFic29sdXRlIHBlcmNlbnRhZ2UgZm9yZWNhc3QgZXJyb3IgKE1BUEUpIikNCiMgTWVhbiBhYnNvbHV0ZSBwZXJjZW50YWdlIGZvcmVjYXN0IGVycm9yIChNQVBFKQ0KbWVhbihhYnMobG9nLldJLmZpbHQyJGZbMTgwMDoxOTA4XSAtIGxvZy5XSS50c1sxODAwOjE5MDhdKSAvIGxvZy5XSS50c1sxODAwOjE5MDhdKQ0KDQpwbG90KGxvZy5XSS5maWx0MiRmLHlsaW09Yyg5LDExKSkNCmxpbmVzKGxvZy5XSS50cyxjb2w9ImdyZWVuIikNCg0KDQpgYGANCg0KYGBge3J9DQojIEZvbGxvd2luZyBzbmlwcGV0IG9mIGNjb2RlIGlzIGZvciBtb2RlbCBkaWFnb25zdGljcw0KIyBHZXQgb25lLXN0ZXAgYWhlYWQgZm9yZWNhc3QgZXJyb3JzDQpyZXMgPC0gcmVzaWR1YWxzKGxvZy5XSS5maWx0Miwgc2Q9RkFMU0UpDQoNCiMgUGxvdCBvbmUtc3RlcCBhaGVhZCBmb3JlY2FzdCBlcnJvcnMNCg0KcGxvdChyZXMsdHlwZT0naCcpOyBhYmxpbmUoaD0wKQ0KcGFyKG1mcm93PWMoMSwyKSkNCmFjZihyZXMsbGFnLm1heCA9IDI2MCkNCnBhY2YocmVzLGxhZy5tYXggPSAyNjApDQoNCiMgUGxvdCBxcS1wbG90IG9mIG9uZS1zdGVwIGFoZWFkIGZvcmVjYXN0IGVycm9ycw0KcXFub3JtKHJlcyk7IHFxbGluZShyZXMpDQoNCg0KIyBUZXN0IG5vcm1hbGl0eSB3aXRoIHRoZSBTaGFwaXJvLVdpbGsgbm9ybWFsaXR5IHRlc3QNCiMgSF8wOiBlcnJvcnMgYXJlIG5vcm1hbGx5IGRpc3RyaWJ1dGlvbg0KIyBIX0E6IGVycm9ycyBhcmUgbm90IG5vcm1hbGx5IGRpc3RyaWJ1dGlvbg0Kc2hhcGlyby50ZXN0KHJlcykNCg0KDQojIFRlc3QgYXV0b2NvcnJlbGF0aW9uIHdpdGggdGhlIExqdW5nLUJveCB0ZXN0DQojIEhfMDogZXJyb3JzIGFyZSBpbmRlcGVuZGVudA0KIyBIX0E6IGVycm9ycyBleGhpYml0IHNlcmlhbCBjb3JyZWxhdGlvbg0KIEJveC50ZXN0KHJlcywgbGFnPTIwLCB0eXBlPSJManVuZyIpICAgDQpzYXBwbHkoMSA6IDIwLCBmdW5jdGlvbihpKQ0KICAgICAgIEJveC50ZXN0KHJlcywgbGFnID0gaSwgdHlwZSA9ICJManVuZy1Cb3giKSRwLnZhbHVlKQ0KDQpgYGANCg0KDQpgYGB7cn0NCmJ1aWxkIDwtIGZ1bmN0aW9uKHBhcm0pIHsNCiAgZGxtTW9kUG9seShvcmRlciA9IDIsIGRWID0gZXhwKHBhcm1bMV0pLCBkVyA9IGMoZXhwKHBhcm1bMl0pLGV4cChwYXJtWzNdKSkpICsgZGxtTW9kVHJpZyhzID0gNywgZFYgPSAwLCBkVz1leHAocGFybVs0XSkpDQp9DQpmaXQgPC0gZGxtTUxFKGxvZy5UWC50cywgcmVwKDAsNCksIGJ1aWxkKQ0KZml0JGNvbnZlcmdlbmNlDQoNCkJJQy4ybmQuc2Vhc2ZhY3RvciA8LSAgMiAqICBmaXQkdmFsdWUgKyBsZW5ndGgoZml0JHBhcikgKiBsb2cobGVuZ3RoKGxvZy5UWC50cykpDQpwcmludCgiQklDIikNCkJJQy4ybmQuc2Vhc2ZhY3Rvcg0KDQptb2RlbC5UWDwtIGJ1aWxkKGZpdCRwYXIpICAjVGhpcyBpcyBwYXJ0IHdoZXJlIGhlIHRha2VzIHRoZSBtb2RlbCBwYXJhbWV0ZXJzDQpwcmludCgiT2JzZXJ2YXRpb25hbCBub2lzZSBmcm9tIE1MRSIpDQptb2RlbC5UWCRWDQpwcmludCgiSW5ub3ZhdGlvbiB2YXJpYW5jZSBtYXRyaXggZGlhZ29uYWwgZWxlbWVudHMgZnJvbSBNTEUiKQ0KbW9kZWwuVFgkV1sxOjIsMToyXQ0KDQpsb2cuVFguZmlsdDIgPC0gZGxtRmlsdGVyKGxvZy5UWC50cywgbW9kZWwuVFgpDQoNCmNvdi5maWx0IDwtIHdpdGgobG9nLlRYLmZpbHQyLCBkbG1TdmQydmFyKFUuQywgRC5DKSkNCg0Kc2Vhcy50ZXJtID0gMg0KDQpzZC5zZWFzb25hbGl0eS5maWx0MiA8LSByZXAoTkEsbGVuZ3RoKGNvdi5maWx0KSkNCmZvcihpIGluIDE6bGVuZ3RoKGNvdi5maWx0KSkgc2Quc2Vhc29uYWxpdHkuZmlsdDJbaV0gPSBzcXJ0KGNvdi5maWx0W1tpXV1bc2Vhcy50ZXJtLHNlYXMudGVybV0pDQpzZC5zZWFzb25hbGl0eS5maWx0MiA9IHRzKHNkLnNlYXNvbmFsaXR5LmZpbHQyWy0oMTo4KV0sZnJlcXVlbmN5PTcpDQpzZWFzb25hbGl0eS5maWx0MiA9IHRzKGxvZy5UWC5maWx0MiRtWy0oMTo4KSxzZWFzLnRlcm1dLGZyZXF1ZW5jeT03KQ0KbGwgPSBzZWFzb25hbGl0eS5maWx0MiAtIDEuOTYgKiBzZC5zZWFzb25hbGl0eS5maWx0Mg0KdWwgPSBzZWFzb25hbGl0eS5maWx0MiArIDEuOTYgKiBzZC5zZWFzb25hbGl0eS5maWx0Mg0KbGxpbSA9IG1pbihsbCkNCnVsaW0gPSBtYXgodWwpDQpwbG90KHNlYXNvbmFsaXR5LmZpbHQyLHlsaW09YyhsbGltLHVsaW0pKQ0KbGluZXMobGwsbHR5PTIsY29sPSJncmVlbiIpDQpsaW5lcyh1bCxsdHk9Mixjb2w9ImdyZWVuIikNCmxsaW0gPSBtaW4oYyhtaW4oc2Vhc29uYWxpdHkuZmlsdDIvc2Quc2Vhc29uYWxpdHkuZmlsdDIpLC0xLjk2KSkNCnVsaW0gPSBtYXgoYyhtYXgoc2Vhc29uYWxpdHkuZmlsdDIvc2Quc2Vhc29uYWxpdHkuZmlsdDIpLDEuOTYpKQ0KcGxvdChzZWFzb25hbGl0eS5maWx0Mi9zZC5zZWFzb25hbGl0eS5maWx0Mix5bGltPWMobGxpbSx1bGltKSkNCmFibGluZShoPTEuOTYsbHR5PTIpDQphYmxpbmUoaD0tMS45NixsdHk9MikNCg0Kc2Vhcy50ZXJtID0gNA0KDQpzZC5zZWFzb25hbGl0eS5maWx0MiA8LSByZXAoTkEsbGVuZ3RoKGNvdi5maWx0KSkNCmZvcihpIGluIDE6bGVuZ3RoKGNvdi5maWx0KSkgc2Quc2Vhc29uYWxpdHkuZmlsdDJbaV0gPSBzcXJ0KGNvdi5maWx0W1tpXV1bc2Vhcy50ZXJtLHNlYXMudGVybV0pDQpzZC5zZWFzb25hbGl0eS5maWx0MiA9IHRzKHNkLnNlYXNvbmFsaXR5LmZpbHQyWy0oMTo4KV0sZnJlcXVlbmN5PTcpDQpzZWFzb25hbGl0eS5maWx0MiA9IHRzKGxvZy5UWC5maWx0MiRtWy0oMTo4KSxzZWFzLnRlcm1dLGZyZXF1ZW5jeT03KQ0KbGwgPSBzZWFzb25hbGl0eS5maWx0MiAtIDEuOTYgKiBzZC5zZWFzb25hbGl0eS5maWx0Mg0KdWwgPSBzZWFzb25hbGl0eS5maWx0MiArIDEuOTYgKiBzZC5zZWFzb25hbGl0eS5maWx0Mg0KbGxpbSA9IG1pbihsbCkNCnVsaW0gPSBtYXgodWwpDQpwbG90KHNlYXNvbmFsaXR5LmZpbHQyLHlsaW09YyhsbGltLHVsaW0pKQ0KbGluZXMobGwsbHR5PTIsY29sPSJncmVlbiIpDQpsaW5lcyh1bCxsdHk9Mixjb2w9ImdyZWVuIikNCmxsaW0gPSBtaW4oYyhtaW4oc2Vhc29uYWxpdHkuZmlsdDIvc2Quc2Vhc29uYWxpdHkuZmlsdDIpLC0xLjk2KSkNCnVsaW0gPSBtYXgoYyhtYXgoc2Vhc29uYWxpdHkuZmlsdDIvc2Quc2Vhc29uYWxpdHkuZmlsdDIpLDEuOTYpKQ0KcGxvdChzZWFzb25hbGl0eS5maWx0Mi9zZC5zZWFzb25hbGl0eS5maWx0Mix5bGltPWMobGxpbSx1bGltKSkNCmFibGluZShoPTEuOTYsbHR5PTIpDQphYmxpbmUoaD0tMS45NixsdHk9MikNCg0KDQoNCnNlYXMudGVybSA9IDYNCg0Kc2Quc2Vhc29uYWxpdHkuZmlsdDIgPC0gcmVwKE5BLGxlbmd0aChjb3YuZmlsdCkpDQpmb3IoaSBpbiAxOmxlbmd0aChjb3YuZmlsdCkpIHNkLnNlYXNvbmFsaXR5LmZpbHQyW2ldID0gc3FydChjb3YuZmlsdFtbaV1dW3NlYXMudGVybSxzZWFzLnRlcm1dKQ0Kc2Quc2Vhc29uYWxpdHkuZmlsdDIgPSB0cyhzZC5zZWFzb25hbGl0eS5maWx0MlstKDE6OCldLGZyZXF1ZW5jeT03KQ0Kc2Vhc29uYWxpdHkuZmlsdDIgPSB0cyhsb2cuVFguZmlsdDIkbVstKDE6OCksc2Vhcy50ZXJtXSxmcmVxdWVuY3k9NykNCmxsID0gc2Vhc29uYWxpdHkuZmlsdDIgLSAxLjk2ICogc2Quc2Vhc29uYWxpdHkuZmlsdDINCnVsID0gc2Vhc29uYWxpdHkuZmlsdDIgKyAxLjk2ICogc2Quc2Vhc29uYWxpdHkuZmlsdDINCmxsaW0gPSBtaW4obGwpDQp1bGltID0gbWF4KHVsKQ0KcGxvdChzZWFzb25hbGl0eS5maWx0Mix5bGltPWMobGxpbSx1bGltKSkNCmxpbmVzKGxsLGx0eT0yLGNvbD0iZ3JlZW4iKQ0KbGluZXModWwsbHR5PTIsY29sPSJncmVlbiIpDQpsbGltID0gbWluKGMobWluKHNlYXNvbmFsaXR5LmZpbHQyL3NkLnNlYXNvbmFsaXR5LmZpbHQyKSwtMS45NikpDQp1bGltID0gbWF4KGMobWF4KHNlYXNvbmFsaXR5LmZpbHQyL3NkLnNlYXNvbmFsaXR5LmZpbHQyKSwxLjk2KSkNCnBsb3Qoc2Vhc29uYWxpdHkuZmlsdDIvc2Quc2Vhc29uYWxpdHkuZmlsdDIseWxpbT1jKGxsaW0sdWxpbSkpDQphYmxpbmUoaD0xLjk2LGx0eT0yKQ0KYWJsaW5lKGg9LTEuOTYsbHR5PTIpDQoNCg0Kc2Vhcy50ZXJtID0gOA0KDQpzZC5zZWFzb25hbGl0eS5maWx0MiA8LSByZXAoTkEsbGVuZ3RoKGNvdi5maWx0KSkNCmZvcihpIGluIDE6bGVuZ3RoKGNvdi5maWx0KSkgc2Quc2Vhc29uYWxpdHkuZmlsdDJbaV0gPSBzcXJ0KGNvdi5maWx0W1tpXV1bc2Vhcy50ZXJtLHNlYXMudGVybV0pDQpzZC5zZWFzb25hbGl0eS5maWx0MiA9IHRzKHNkLnNlYXNvbmFsaXR5LmZpbHQyWy0oMTo4KV0sZnJlcXVlbmN5PTcpDQpzZWFzb25hbGl0eS5maWx0MiA9IHRzKGxvZy5UWC5maWx0MiRtWy0oMTo4KSxzZWFzLnRlcm1dLGZyZXF1ZW5jeT03KQ0KbGwgPSBzZWFzb25hbGl0eS5maWx0MiAtIDEuOTYgKiBzZC5zZWFzb25hbGl0eS5maWx0Mg0KdWwgPSBzZWFzb25hbGl0eS5maWx0MiArIDEuOTYgKiBzZC5zZWFzb25hbGl0eS5maWx0Mg0KbGxpbSA9IG1pbihsbCkNCnVsaW0gPSBtYXgodWwpDQpwbG90KHNlYXNvbmFsaXR5LmZpbHQyLHlsaW09YyhsbGltLHVsaW0pKQ0KbGluZXMobGwsbHR5PTIsY29sPSJncmVlbiIpDQpsaW5lcyh1bCxsdHk9Mixjb2w9ImdyZWVuIikNCmxsaW0gPSBtaW4oYyhtaW4oc2Vhc29uYWxpdHkuZmlsdDIvc2Quc2Vhc29uYWxpdHkuZmlsdDIpLC0xLjk2KSkNCnVsaW0gPSBtYXgoYyhtYXgoc2Vhc29uYWxpdHkuZmlsdDIvc2Quc2Vhc29uYWxpdHkuZmlsdDIpLDEuOTYpKQ0KcGxvdChzZWFzb25hbGl0eS5maWx0Mi9zZC5zZWFzb25hbGl0eS5maWx0Mix5bGltPWMobGxpbSx1bGltKSkNCmFibGluZShoPTEuOTYsbHR5PTIpDQphYmxpbmUoaD0tMS45NixsdHk9MikNCg0KDQoNCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjDQojICAgRm9yZWNhc3RpbmcgICAjDQojIyMjIyMjIyMjIyMjIyMjIyMjDQoNCnByZWRpY3Rpb25zIDwtIGRsbUZvcmVjYXN0KGxvZy5UWC5maWx0Miwgbj0yOCkNCg0KbGwgPSBwcmVkaWN0aW9ucyRmIC0gMS45NiAqIHNxcnQodW5saXN0KHByZWRpY3Rpb25zJFEpKQ0KdWwgPSBwcmVkaWN0aW9ucyRmICsgMS45NiAqIHNxcnQodW5saXN0KHByZWRpY3Rpb25zJFEpKQ0KcGxvdChsb2cuVFgudHMsIHhsYWIgPSAiIiwgY29sID0gImRhcmtncmV5Iix4bGltPWMoMjUwLDMwMCksbHdkPTIpDQojcGxvdChsb2cuY2hvYywgeGxhYiA9ICIiLCBjb2wgPSAiZGFya2dyZXkiLHhsaW09YygxOTU4LDIwMDApLCB5bGltPWMoMTAwMCwxMDAwMCksbHdkPTIpDQpsaW5lcyhwcmVkaWN0aW9ucyRmLCBjb2w9InJlZCIsbHdkPTIpDQpsaW5lcyhsbCxsdHk9MiwgY29sPSJncmVlbiIsbHdkPTIpDQpsaW5lcyh1bCxsdHk9MiwgY29sPSJncmVlbiIsbHdkPTIpDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyAgICAgICAgICBPbmUtc3RlcCBhaGVhZCBmb3JlY2FzdCBlcnJvciBmb3IgdGhlIGxhc3QgOSB5ZWFycyAgICAgICAgICAgICAgICAjDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCnByaW50KCIgTWVhbiBhYnNvbHV0ZSBmb3JlY2FzdCBlcnJvciIpDQojIE1lYW4gYWJzb2x1dGUgZm9yZWNhc3QgZXJyb3IgKE1BRSkNCm1lYW4oYWJzKGxvZy5UWC5maWx0MiRmWzE4MDA6MTkwOF0gLSBsb2cuVFgudHNbMTgwMDoxOTA4XSkpDQoNCnByaW50KCIgTWVhbiBzcXVhcmVkIGZvcmVjYXN0IGVycm9yIChNU0UpIikNCiMgTWVhbiBzcXVhcmVkIGZvcmVjYXN0IGVycm9yIChNU0UpDQptZWFuKChsb2cuV0kuZmlsdDIkZlsxODAwOjE5MDhdIC0gbG9nLldJLnRzWzE4MDA6MTkwOF0pXjIpDQoNCnByaW50KCIgTWVhbiBhYnNvbHV0ZSBwZXJjZW50YWdlIGZvcmVjYXN0IGVycm9yIChNQVBFKSIpDQojIE1lYW4gYWJzb2x1dGUgcGVyY2VudGFnZSBmb3JlY2FzdCBlcnJvciAoTUFQRSkNCm1lYW4oYWJzKGxvZy5XSS5maWx0MiRmWzE4MDA6MTkwOF0gLSBsb2cuV0kudHNbMTgwMDoxOTA4XSkgLyBsb2cuV0kudHNbMTgwMDoxOTA4XSkNCg0KcGxvdChsb2cuV0kuZmlsdDIkZix5bGltPWMoOCwxMCkpDQpsaW5lcyhsb2cuV0kudHMsY29sPSJncmVlbiIpDQoNCmBgYA0KDQpgYGB7cn0NCiMgRm9sbG93aW5nIHNuaXBwZXQgb2YgY2NvZGUgaXMgZm9yIG1vZGVsIGRpYWdvbnN0aWNzDQojIEdldCBvbmUtc3RlcCBhaGVhZCBmb3JlY2FzdCBlcnJvcnMNCnJlcyA8LSByZXNpZHVhbHMobG9nLlRYLmZpbHQyLCBzZD1GQUxTRSkNCg0KIyBQbG90IG9uZS1zdGVwIGFoZWFkIGZvcmVjYXN0IGVycm9ycw0KDQpwbG90KHJlcyx0eXBlPSdoJyk7IGFibGluZShoPTApDQpwYXIobWZyb3c9YygxLDIpKQ0KYWNmKHJlcyxsYWcubWF4ID0gMjYwKQ0KcGFjZihyZXMsbGFnLm1heCA9IDI2MCkNCg0KIyBQbG90IHFxLXBsb3Qgb2Ygb25lLXN0ZXAgYWhlYWQgZm9yZWNhc3QgZXJyb3JzDQpxcW5vcm0ocmVzKTsgcXFsaW5lKHJlcykNCg0KDQojIFRlc3Qgbm9ybWFsaXR5IHdpdGggdGhlIFNoYXBpcm8tV2lsayBub3JtYWxpdHkgdGVzdA0KIyBIXzA6IGVycm9ycyBhcmUgbm9ybWFsbHkgZGlzdHJpYnV0aW9uDQojIEhfQTogZXJyb3JzIGFyZSBub3Qgbm9ybWFsbHkgZGlzdHJpYnV0aW9uDQpzaGFwaXJvLnRlc3QocmVzKQ0KDQoNCiMgVGVzdCBhdXRvY29ycmVsYXRpb24gd2l0aCB0aGUgTGp1bmctQm94IHRlc3QNCiMgSF8wOiBlcnJvcnMgYXJlIGluZGVwZW5kZW50DQojIEhfQTogZXJyb3JzIGV4aGliaXQgc2VyaWFsIGNvcnJlbGF0aW9uDQogQm94LnRlc3QocmVzLCBsYWc9MjAsIHR5cGU9IkxqdW5nIikgICANCnNhcHBseSgxIDogMjAsIGZ1bmN0aW9uKGkpDQogICAgICAgQm94LnRlc3QocmVzLCBsYWcgPSBpLCB0eXBlID0gIkxqdW5nLUJveCIpJHAudmFsdWUpDQoNCmBgYA0KYGBge3J9DQoNCmV4dHJhY3RfZnVuY190cyA8LSBmdW5jdGlvbihuZXd0cyl7DQpyZW1vdmUobG9nLlRYLnRzKQ0KYnVpbGQgPC0gZnVuY3Rpb24ocGFybSkgew0KICBkbG1Nb2RQb2x5KG9yZGVyID0gMiwgZFYgPSBleHAocGFybVsxXSksIGRXID0gYyhleHAocGFybVsyXSksZXhwKHBhcm1bM10pKSkgKyBkbG1Nb2RUcmlnKHMgPSA3LCBkViA9IDAsIGRXPWV4cChwYXJtWzRdKSkNCn0NCmZpdCA8LSBkbG1NTEUobmV3dHMsIHJlcCgwLDQpLCBidWlsZCkNCmZpdCRjb252ZXJnZW5jZQ0KDQpCSUMuMm5kLnNlYXNmYWN0b3IgPC0gIDIgKiAgZml0JHZhbHVlICsgbGVuZ3RoKGZpdCRwYXIpICogbG9nKGxlbmd0aChuZXd0cykpDQpwcmludCgiQklDIikNCkJJQy4ybmQuc2Vhc2ZhY3Rvcg0KDQptb2RlbC5UWDwtIGJ1aWxkKGZpdCRwYXIpICAjVGhpcyBpcyBwYXJ0IHdoZXJlIGhlIHRha2VzIHRoZSBtb2RlbCBwYXJhbWV0ZXJzDQpwcmludCgiT2JzZXJ2YXRpb25hbCBub2lzZSBmcm9tIE1MRSIpDQptb2RlbC5UWCRWDQpwcmludCgiSW5ub3ZhdGlvbiB2YXJpYW5jZSBtYXRyaXggZGlhZ29uYWwgZWxlbWVudHMgZnJvbSBNTEUiKQ0KbW9kZWwuVFgkV1sxOjIsMToyXQ0KDQpsb2cuVFguZmlsdDIgPC0gZGxtRmlsdGVyKG5ld3RzLCBtb2RlbC5UWCkNCg0KY292LmZpbHQgPC0gd2l0aChsb2cuVFguZmlsdDIsIGRsbVN2ZDJ2YXIoVS5DLCBELkMpKQ0KDQpzZWFzLnRlcm0gPSAyDQoNCnNkLnNlYXNvbmFsaXR5LmZpbHQyIDwtIHJlcChOQSxsZW5ndGgoY292LmZpbHQpKQ0KZm9yKGkgaW4gMTpsZW5ndGgoY292LmZpbHQpKSBzZC5zZWFzb25hbGl0eS5maWx0MltpXSA9IHNxcnQoY292LmZpbHRbW2ldXVtzZWFzLnRlcm0sc2Vhcy50ZXJtXSkNCnNkLnNlYXNvbmFsaXR5LmZpbHQyID0gdHMoc2Quc2Vhc29uYWxpdHkuZmlsdDJbLSgxOjgpXSxmcmVxdWVuY3k9NykNCnNlYXNvbmFsaXR5LmZpbHQyID0gdHMobG9nLlRYLmZpbHQyJG1bLSgxOjgpLHNlYXMudGVybV0sZnJlcXVlbmN5PTcpDQpsbCA9IHNlYXNvbmFsaXR5LmZpbHQyIC0gMS45NiAqIHNkLnNlYXNvbmFsaXR5LmZpbHQyDQp1bCA9IHNlYXNvbmFsaXR5LmZpbHQyICsgMS45NiAqIHNkLnNlYXNvbmFsaXR5LmZpbHQyDQpsbGltID0gbWluKGxsKQ0KdWxpbSA9IG1heCh1bCkNCnBsb3Qoc2Vhc29uYWxpdHkuZmlsdDIseWxpbT1jKGxsaW0sdWxpbSkpDQpsaW5lcyhsbCxsdHk9Mixjb2w9ImdyZWVuIikNCmxpbmVzKHVsLGx0eT0yLGNvbD0iZ3JlZW4iKQ0KbGxpbSA9IG1pbihjKG1pbihzZWFzb25hbGl0eS5maWx0Mi9zZC5zZWFzb25hbGl0eS5maWx0MiksLTEuOTYpKQ0KdWxpbSA9IG1heChjKG1heChzZWFzb25hbGl0eS5maWx0Mi9zZC5zZWFzb25hbGl0eS5maWx0MiksMS45NikpDQpwbG90KHNlYXNvbmFsaXR5LmZpbHQyL3NkLnNlYXNvbmFsaXR5LmZpbHQyLHlsaW09YyhsbGltLHVsaW0pKQ0KYWJsaW5lKGg9MS45NixsdHk9MikNCmFibGluZShoPS0xLjk2LGx0eT0yKQ0KDQpzZWFzLnRlcm0gPSA0DQoNCnNkLnNlYXNvbmFsaXR5LmZpbHQyIDwtIHJlcChOQSxsZW5ndGgoY292LmZpbHQpKQ0KZm9yKGkgaW4gMTpsZW5ndGgoY292LmZpbHQpKSBzZC5zZWFzb25hbGl0eS5maWx0MltpXSA9IHNxcnQoY292LmZpbHRbW2ldXVtzZWFzLnRlcm0sc2Vhcy50ZXJtXSkNCnNkLnNlYXNvbmFsaXR5LmZpbHQyID0gdHMoc2Quc2Vhc29uYWxpdHkuZmlsdDJbLSgxOjgpXSxmcmVxdWVuY3k9NykNCnNlYXNvbmFsaXR5LmZpbHQyID0gdHMobG9nLlRYLmZpbHQyJG1bLSgxOjgpLHNlYXMudGVybV0sZnJlcXVlbmN5PTcpDQpsbCA9IHNlYXNvbmFsaXR5LmZpbHQyIC0gMS45NiAqIHNkLnNlYXNvbmFsaXR5LmZpbHQyDQp1bCA9IHNlYXNvbmFsaXR5LmZpbHQyICsgMS45NiAqIHNkLnNlYXNvbmFsaXR5LmZpbHQyDQpsbGltID0gbWluKGxsKQ0KdWxpbSA9IG1heCh1bCkNCnBsb3Qoc2Vhc29uYWxpdHkuZmlsdDIseWxpbT1jKGxsaW0sdWxpbSkpDQpsaW5lcyhsbCxsdHk9Mixjb2w9ImdyZWVuIikNCmxpbmVzKHVsLGx0eT0yLGNvbD0iZ3JlZW4iKQ0KbGxpbSA9IG1pbihjKG1pbihzZWFzb25hbGl0eS5maWx0Mi9zZC5zZWFzb25hbGl0eS5maWx0MiksLTEuOTYpKQ0KdWxpbSA9IG1heChjKG1heChzZWFzb25hbGl0eS5maWx0Mi9zZC5zZWFzb25hbGl0eS5maWx0MiksMS45NikpDQpwbG90KHNlYXNvbmFsaXR5LmZpbHQyL3NkLnNlYXNvbmFsaXR5LmZpbHQyLHlsaW09YyhsbGltLHVsaW0pKQ0KYWJsaW5lKGg9MS45NixsdHk9MikNCmFibGluZShoPS0xLjk2LGx0eT0yKQ0KDQoNCg0Kc2Vhcy50ZXJtID0gNg0KDQpzZC5zZWFzb25hbGl0eS5maWx0MiA8LSByZXAoTkEsbGVuZ3RoKGNvdi5maWx0KSkNCmZvcihpIGluIDE6bGVuZ3RoKGNvdi5maWx0KSkgc2Quc2Vhc29uYWxpdHkuZmlsdDJbaV0gPSBzcXJ0KGNvdi5maWx0W1tpXV1bc2Vhcy50ZXJtLHNlYXMudGVybV0pDQpzZC5zZWFzb25hbGl0eS5maWx0MiA9IHRzKHNkLnNlYXNvbmFsaXR5LmZpbHQyWy0oMTo4KV0sZnJlcXVlbmN5PTcpDQpzZWFzb25hbGl0eS5maWx0MiA9IHRzKGxvZy5UWC5maWx0MiRtWy0oMTo4KSxzZWFzLnRlcm1dLGZyZXF1ZW5jeT03KQ0KbGwgPSBzZWFzb25hbGl0eS5maWx0MiAtIDEuOTYgKiBzZC5zZWFzb25hbGl0eS5maWx0Mg0KdWwgPSBzZWFzb25hbGl0eS5maWx0MiArIDEuOTYgKiBzZC5zZWFzb25hbGl0eS5maWx0Mg0KbGxpbSA9IG1pbihsbCkNCnVsaW0gPSBtYXgodWwpDQpwbG90KHNlYXNvbmFsaXR5LmZpbHQyLHlsaW09YyhsbGltLHVsaW0pKQ0KbGluZXMobGwsbHR5PTIsY29sPSJncmVlbiIpDQpsaW5lcyh1bCxsdHk9Mixjb2w9ImdyZWVuIikNCmxsaW0gPSBtaW4oYyhtaW4oc2Vhc29uYWxpdHkuZmlsdDIvc2Quc2Vhc29uYWxpdHkuZmlsdDIpLC0xLjk2KSkNCnVsaW0gPSBtYXgoYyhtYXgoc2Vhc29uYWxpdHkuZmlsdDIvc2Quc2Vhc29uYWxpdHkuZmlsdDIpLDEuOTYpKQ0KcGxvdChzZWFzb25hbGl0eS5maWx0Mi9zZC5zZWFzb25hbGl0eS5maWx0Mix5bGltPWMobGxpbSx1bGltKSkNCmFibGluZShoPTEuOTYsbHR5PTIpDQphYmxpbmUoaD0tMS45NixsdHk9MikNCg0KDQpzZWFzLnRlcm0gPSA4DQoNCnNkLnNlYXNvbmFsaXR5LmZpbHQyIDwtIHJlcChOQSxsZW5ndGgoY292LmZpbHQpKQ0KZm9yKGkgaW4gMTpsZW5ndGgoY292LmZpbHQpKSBzZC5zZWFzb25hbGl0eS5maWx0MltpXSA9IHNxcnQoY292LmZpbHRbW2ldXVtzZWFzLnRlcm0sc2Vhcy50ZXJtXSkNCnNkLnNlYXNvbmFsaXR5LmZpbHQyID0gdHMoc2Quc2Vhc29uYWxpdHkuZmlsdDJbLSgxOjgpXSxmcmVxdWVuY3k9NykNCnNlYXNvbmFsaXR5LmZpbHQyID0gdHMobG9nLlRYLmZpbHQyJG1bLSgxOjgpLHNlYXMudGVybV0sZnJlcXVlbmN5PTcpDQpsbCA9IHNlYXNvbmFsaXR5LmZpbHQyIC0gMS45NiAqIHNkLnNlYXNvbmFsaXR5LmZpbHQyDQp1bCA9IHNlYXNvbmFsaXR5LmZpbHQyICsgMS45NiAqIHNkLnNlYXNvbmFsaXR5LmZpbHQyDQpsbGltID0gbWluKGxsKQ0KdWxpbSA9IG1heCh1bCkNCnBsb3Qoc2Vhc29uYWxpdHkuZmlsdDIseWxpbT1jKGxsaW0sdWxpbSkpDQpsaW5lcyhsbCxsdHk9Mixjb2w9ImdyZWVuIikNCmxpbmVzKHVsLGx0eT0yLGNvbD0iZ3JlZW4iKQ0KbGxpbSA9IG1pbihjKG1pbihzZWFzb25hbGl0eS5maWx0Mi9zZC5zZWFzb25hbGl0eS5maWx0MiksLTEuOTYpKQ0KdWxpbSA9IG1heChjKG1heChzZWFzb25hbGl0eS5maWx0Mi9zZC5zZWFzb25hbGl0eS5maWx0MiksMS45NikpDQpwbG90KHNlYXNvbmFsaXR5LmZpbHQyL3NkLnNlYXNvbmFsaXR5LmZpbHQyLHlsaW09YyhsbGltLHVsaW0pKQ0KYWJsaW5lKGg9MS45NixsdHk9MikNCmFibGluZShoPS0xLjk2LGx0eT0yKQ0KDQoNCg0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgICBGb3JlY2FzdGluZyAgICMNCiMjIyMjIyMjIyMjIyMjIyMjIyMNCg0KcHJlZGljdGlvbnMgPC0gZGxtRm9yZWNhc3QobG9nLlRYLmZpbHQyLCBuPTI4KQ0KDQpsbCA9IHByZWRpY3Rpb25zJGYgLSAxLjk2ICogc3FydCh1bmxpc3QocHJlZGljdGlvbnMkUSkpDQp1bCA9IHByZWRpY3Rpb25zJGYgKyAxLjk2ICogc3FydCh1bmxpc3QocHJlZGljdGlvbnMkUSkpDQpwbG90KG5ld3RzLCB4bGFiID0gIiIsIGNvbCA9ICJkYXJrZ3JleSIseGxpbT1jKDI1MCwzMDApLGx3ZD0yKQ0KI3Bsb3QobG9nLmNob2MsIHhsYWIgPSAiIiwgY29sID0gImRhcmtncmV5Iix4bGltPWMoMTk1OCwyMDAwKSwgeWxpbT1jKDEwMDAsMTAwMDApLGx3ZD0yKQ0KbGluZXMocHJlZGljdGlvbnMkZiwgY29sPSJyZWQiLGx3ZD0yKQ0KbGluZXMobGwsbHR5PTIsIGNvbD0iZ3JlZW4iLGx3ZD0yKQ0KbGluZXModWwsbHR5PTIsIGNvbD0iZ3JlZW4iLGx3ZD0yKQ0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgICAgICAgICAgT25lLXN0ZXAgYWhlYWQgZm9yZWNhc3QgZXJyb3IgZm9yIHRoZSBsYXN0IDkgeWVhcnMgICAgICAgICAgICAgICAgIw0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQpwcmludCgiIE1lYW4gYWJzb2x1dGUgZm9yZWNhc3QgZXJyb3IiKQ0KIyBNZWFuIGFic29sdXRlIGZvcmVjYXN0IGVycm9yIChNQUUpDQptZWFuKGFicyhsb2cuVFguZmlsdDIkZlsxODAwOjE5MDhdIC0gbmV3dHNbMTgwMDoxOTA4XSkpDQoNCnByaW50KCIgTWVhbiBzcXVhcmVkIGZvcmVjYXN0IGVycm9yIChNU0UpIikNCiMgTWVhbiBzcXVhcmVkIGZvcmVjYXN0IGVycm9yIChNU0UpDQptZWFuKChsb2cuVFguZmlsdDIkZlsxODAwOjE5MDhdIC0gbmV3dHNbMTgwMDoxOTA4XSleMikNCg0KcHJpbnQoIiBNZWFuIGFic29sdXRlIHBlcmNlbnRhZ2UgZm9yZWNhc3QgZXJyb3IgKE1BUEUpIikNCiMgTWVhbiBhYnNvbHV0ZSBwZXJjZW50YWdlIGZvcmVjYXN0IGVycm9yIChNQVBFKQ0KbWVhbihhYnMobG9nLlRYLmZpbHQyJGZbMTgwMDoxOTA4XSAtIG5ld3RzWzE4MDA6MTkwOF0pIC8gbmV3dHNbMTgwMDoxOTA4XSkNCg0KcGxvdChsb2cuVFguZmlsdDIkZix5bGltPWMoOCwxMCkpDQpsaW5lcyhuZXd0cyxjb2w9ImdyZWVuIikgDQp9DQpgYGANCg0K